Skip to content

Commit 4d57be0

Browse files
committed
Implement JU5&6 backbones for instrumentation modules
A few bridge APIs were needed to overcome incompatibilities between the versions
1 parent 0e0dc13 commit 4d57be0

19 files changed

Lines changed: 140 additions & 48 deletions

File tree

build-logic/gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" }
6666
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params" }
6767
junit-platform-commons = { module = "org.junit.platform:junit-platform-commons" }
6868
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" }
69-
junit-platform-runner = { module = "org.junit.platform:junit-platform-runner" }
69+
junit-platform-suiteapi = { module = "org.junit.platform:junit-platform-suite-api" }
7070
junit-vintage-api = { module = "junit:junit", version.ref = "junit4" }
7171
junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine" }
7272
konftoml = { module = "com.uchuhimo:konf-toml", version.ref = "konftoml" }

instrumentation/build.gradle.kts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,14 @@ subprojects {
3535

3636
val jvmTarget = JvmTarget.JVM_21
3737
val javaVersion = JavaVersion.toVersion(jvmTarget.target)
38-
38+
3939
// Configure Kotlin
4040
plugins.withType<KotlinBasePlugin> {
4141
tasks.withType<KotlinCompilationTask<*>>().configureEach {
4242
compilerOptions {
4343
this.progressiveMode.set(true)
4444
if (this is KotlinJvmCompilerOptions) {
4545
this.jvmTarget.set(jvmTarget)
46-
this.freeCompilerArgs.add("-Xjvm-default=all")
4746
}
4847
}
4948
}

instrumentation/core/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ dependencies {
4141
// This is required by the "instrumentation-runner" companion library,
4242
// since it can't provide any JUnit 5 runtime libraries itself
4343
// due to fear of prematurely incrementing the minSdkVersion requirement.
44-
runtimeOnly(libs.junit.platform.runner)
44+
runtimeOnly(libs.junit.platform.launcher)
45+
runtimeOnly(libs.junit.platform.suiteapi)
4546
runtimeOnly(libs.junit.jupiter.engine)
4647

4748
// This transitive dependency of JUnit 5 is required to be on the runtime classpath,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package de.mannodermaus.junit5.internal.compat
2+
3+
import org.junit.jupiter.api.extension.ExtensionContext
4+
import kotlin.reflect.KClass
5+
6+
// JUnit 5 facade of ExtensionContext.Store APIs
7+
// that were deprecated/removed in subsequent versions of the framework.
8+
9+
internal fun <K : Any, V : Any> ExtensionContext.Store.computeIfAbsentCompat(
10+
key: K,
11+
defaultCreator: (K) -> V
12+
): Any = getOrComputeIfAbsent(key, defaultCreator)
13+
14+
internal fun <K : Any, V : Any> ExtensionContext.Store.computeIfAbsentCompat(
15+
key: K,
16+
defaultCreator: (K) -> V,
17+
requiredType: KClass<V>
18+
): V = getOrComputeIfAbsent(key, defaultCreator, requiredType.java)

instrumentation/core/src/main/java/de/mannodermaus/junit5/ActivityScenarioExtension.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import android.util.Log
88
import androidx.test.core.app.ActivityScenario
99
import de.mannodermaus.junit5.ActivityScenarioExtension.Companion.launch
1010
import de.mannodermaus.junit5.internal.LOG_TAG
11+
import de.mannodermaus.junit5.internal.compat.computeIfAbsentCompat
1112
import org.junit.jupiter.api.extension.AfterEachCallback
1213
import org.junit.jupiter.api.extension.BeforeEachCallback
1314
import org.junit.jupiter.api.extension.ExtensionContext
@@ -209,10 +210,10 @@ private constructor(private val scenarioSupplier: () -> ActivityScenario<A>) : B
209210
// Create a global lock for restricting test execution to one-by-one;
210211
// this is necessary to ensure that only one ActivityScenario is ever active at a time,
211212
// preventing violations of Android's instrumentation and Espresso
212-
val lock = store.getOrComputeIfAbsent(
213-
/* key = */ LOCK_KEY,
214-
/* defaultCreator = */ { ReentrantLock() },
215-
/* requiredType = */ ReentrantLock::class.java,
213+
val lock = store.computeIfAbsentCompat(
214+
key = LOCK_KEY,
215+
defaultCreator = { ReentrantLock() },
216+
requiredType = ReentrantLock::class,
216217
)
217218

218219
if (state) {
@@ -223,7 +224,7 @@ private constructor(private val scenarioSupplier: () -> ActivityScenario<A>) : B
223224
}
224225

225226
private fun logConcurrentExecutionWarningOnce(store: ExtensionContext.Store) {
226-
store.getOrComputeIfAbsent(WARNING_KEY) {
227+
store.computeIfAbsentCompat(WARNING_KEY) {
227228
setOf(
228229
" [WARNING!] UI tests using ActivityScenarioExtension should not be executed in CONCURRENT mode.",
229230
" We will try to disable parallelism for Espresso tests, but this may be error-prone",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package de.mannodermaus.junit5.internal.compat
2+
3+
import org.junit.jupiter.api.extension.ExtensionContext
4+
import kotlin.reflect.KClass
5+
6+
// JUnit 6 facade of ExtensionContext.Store APIs
7+
// that didn't exist in previous versions of the framework.
8+
9+
internal fun <K : Any, V : Any> ExtensionContext.Store.computeIfAbsentCompat(
10+
key: K,
11+
defaultCreator: (K) -> V
12+
): Any = computeIfAbsent(key, defaultCreator)
13+
14+
internal fun <K : Any, V : Any> ExtensionContext.Store.computeIfAbsentCompat(
15+
key: K,
16+
defaultCreator: (K) -> V,
17+
requiredType: KClass<V>
18+
): V = computeIfAbsent(key, defaultCreator, requiredType.java)

instrumentation/extensions/src/main/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal constructor(private val permissionGranter: PermissionGranter) : BeforeE
6666

6767
/* BeforeEachCallback */
6868

69-
override fun beforeEach(context: ExtensionContext?) {
69+
override fun beforeEach(context: ExtensionContext) {
7070
permissionGranter.requestPermissions()
7171
}
7272
}

instrumentation/extensions/src/test/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtensionTests.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import org.junit.jupiter.api.DynamicTest
99
import org.junit.jupiter.api.DynamicTest.dynamicTest
1010
import org.junit.jupiter.api.Test
1111
import org.junit.jupiter.api.TestFactory
12+
import org.junit.jupiter.api.extension.ExtensionContext
13+
import org.mockito.Mockito.mock
1214
import java.lang.reflect.Modifier
1315

1416
class GrantPermissionExtensionTests {
@@ -81,8 +83,10 @@ class GrantPermissionExtensionTests {
8183

8284
private fun runExtension(vararg permissions: String) {
8385
val extension = GrantPermissionExtension(granter)
86+
val context = mock<ExtensionContext>()
87+
8488
extension.grantPermissions(permissions)
85-
extension.beforeEach(null)
89+
extension.beforeEach(context)
8690
}
8791

8892
private class TestPermissionGranter : PermissionGranter {

instrumentation/runner/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ dependencies {
3434
// by the "instrumentation" companion library instead.
3535
compileOnly(libs.junit.jupiter.api)
3636
compileOnly(libs.junit.jupiter.params)
37-
compileOnly(libs.junit.platform.runner)
37+
compileOnly(libs.junit.platform.launcher)
38+
compileOnly(libs.junit.platform.suiteapi)
3839

3940
testImplementation(project(":testutil"))
4041
testImplementation(libs.robolectric)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package de.mannodermaus.junit5.internal.discovery
2+
3+
import androidx.annotation.RequiresApi
4+
import org.junit.platform.engine.ConfigurationParameters
5+
import java.util.Optional
6+
7+
/**
8+
* JUnit 5 version of the [ConfigurationParameters] interface,
9+
* including the deprecated APIs that were removed in subsequent versions of the framework.
10+
*/
11+
@RequiresApi(26)
12+
internal object EmptyConfigurationParameters : ConfigurationParameters {
13+
override fun get(key: String) = Optional.empty<String>()
14+
override fun getBoolean(key: String) = Optional.empty<Boolean>()
15+
override fun keySet() = emptySet<String>()
16+
17+
@Deprecated("Deprecated in Java", ReplaceWith("keySet().size"))
18+
override fun size() = 0
19+
}

0 commit comments

Comments
 (0)