diff --git a/robolectric-extension/build.gradle b/robolectric-extension/build.gradle index e594b51..77e7d9e 100644 --- a/robolectric-extension/build.gradle +++ b/robolectric-extension/build.gradle @@ -2,7 +2,6 @@ import org.robolectric.gradle.AarDepsPlugin plugins { alias(libs.plugins.kotlinJvm) - } apply plugin: AarDepsPlugin diff --git a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/AndroidMainThreadExecutor.kt b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/AndroidMainThreadExecutor.kt new file mode 100644 index 0000000..02b1946 --- /dev/null +++ b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/AndroidMainThreadExecutor.kt @@ -0,0 +1,33 @@ +package tech.apter.junit.jupiter.robolectric.internal + +import java.util.concurrent.Callable +import java.util.concurrent.ExecutionException +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory +import org.robolectric.util.Util + +internal object AndroidMainThreadExecutor { + private val executorService: ExecutorService = Executors.newSingleThreadExecutor(mainThreadFactory()) + + fun execute(callable: Callable): T { + val future = executorService.submit(callable) + try { + return future.get() + } catch (e: InterruptedException) { + future.cancel(true) + throw RuntimeException(e) + } catch (e: ExecutionException) { + throw Util.sneakyThrow(e.cause) + } + } + + fun shutdown() = executorService.shutdown() + + private fun mainThreadFactory(): ThreadFactory { + return ThreadFactory { r: Runnable? -> + val name = "Android SDK" + Thread(ThreadGroup(name), r, "$name Main Thread") + } + } +} diff --git a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricAndroidSandbox.kt b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricAndroidSandbox.kt new file mode 100644 index 0000000..6de18af --- /dev/null +++ b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricAndroidSandbox.kt @@ -0,0 +1,32 @@ +package tech.apter.junit.jupiter.robolectric.internal + +import java.util.concurrent.Callable +import org.robolectric.ApkLoader +import org.robolectric.annotation.SQLiteMode +import org.robolectric.internal.AndroidSandbox +import org.robolectric.internal.ResourcesMode +import org.robolectric.internal.bytecode.ShadowProviders +import org.robolectric.pluginapi.Sdk + +internal class JUnit5RobolectricAndroidSandbox( + runtimeSdk: Sdk, + compileSdk: Sdk, + resourcesMode: ResourcesMode, + apkLoader: ApkLoader, + testEnvironmentSpec: TestEnvironmentSpec, + sdkSandboxClassLoader: SdkSandboxClassLoader, + shadowProviders: ShadowProviders, + sqLiteMode: SQLiteMode.Mode, +) : AndroidSandbox( + runtimeSdk, + compileSdk, + resourcesMode, + apkLoader, + testEnvironmentSpec, + sdkSandboxClassLoader, + shadowProviders, + sqLiteMode, +) { + override fun runOnMainThread(callable: Callable): T = + AndroidMainThreadExecutor.execute(callable) +} diff --git a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricSandboxBuilder.kt b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricSandboxBuilder.kt index 09984ef..783dc6d 100644 --- a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricSandboxBuilder.kt +++ b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricSandboxBuilder.kt @@ -29,8 +29,9 @@ internal class JUnit5RobolectricSandboxBuilder @Inject constructor( resourcesMode: ResourcesMode, sqLiteMode: SQLiteMode.Mode, ): AndroidSandbox { + logger.trace { "build" } val sdkSandboxClassLoader = getOrCreateClassLoader(instrumentationConfig, runtimeSdk) - return AndroidSandbox( + return JUnit5RobolectricAndroidSandbox( runtimeSdk, compileSdk, resourcesMode, @@ -46,7 +47,7 @@ internal class JUnit5RobolectricSandboxBuilder @Inject constructor( instrumentationConfig: InstrumentationConfiguration, runtimeSdk: Sdk, ): SdkSandboxClassLoader { - val key = Key(instrumentationConfig, runtimeSdk, classInstrumentor) + val key = Key(instrumentationConfig, runtimeSdk) return classLoaderCache.getOrPut(key) { logger.debug { "${SdkSandboxClassLoader::class.simpleName} instance created for $key." } SdkSandboxClassLoader(instrumentationConfig, runtimeSdk, classInstrumentor) @@ -56,7 +57,6 @@ internal class JUnit5RobolectricSandboxBuilder @Inject constructor( private data class Key( private val configuration: InstrumentationConfiguration, private val runtimeSdk: Sdk, - private val classInstrumentor: ClassInstrumentor, ) private companion object {