Use UnboundedSdkLevel for DevSdkIgnoreRule
UnboundedSdkLevel provides a generic and supported way to check for
development SDK level, which makes it unnecessary to update
DevSdkIgnoreRule yearly.
Also this allows using UDC with DevSdkIgnoreRule / DevSdkIgnoreRunner.
Test: Tests using this rule
Change-Id: I151df06ce1498ecbf81c01de8884ebbac83cf7d7
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/CompatUtil.kt b/staticlibs/testutils/devicetests/com/android/testutils/CompatUtil.kt
index ff8c668..82f1d9b 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/CompatUtil.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/CompatUtil.kt
@@ -17,7 +17,7 @@
package com.android.testutils
import android.net.NetworkSpecifier
-import android.os.Build
+import com.android.modules.utils.build.SdkLevel.isAtLeastS
/**
* Test utility to create [NetworkSpecifier]s on different SDK versions.
@@ -26,7 +26,7 @@
@JvmStatic
fun makeTestNetworkSpecifier(ifName: String): NetworkSpecifier {
// Until R, there was no TestNetworkSpecifier, StringNetworkSpecifier was used instead
- if (isDevSdkInRange(minExclusive = null, maxInclusive = Build.VERSION_CODES.R)) {
+ if (!isAtLeastS()) {
return makeNetworkSpecifierInternal("android.net.StringNetworkSpecifier", ifName)
}
// TestNetworkSpecifier is not part of the SDK in some branches using this utility
@@ -37,7 +37,7 @@
@JvmStatic
fun makeEthernetNetworkSpecifier(ifName: String): NetworkSpecifier {
// Until R, there was no EthernetNetworkSpecifier, StringNetworkSpecifier was used instead
- if (isDevSdkInRange(minExclusive = null, maxInclusive = Build.VERSION_CODES.R)) {
+ if (!isAtLeastS()) {
return makeNetworkSpecifierInternal("android.net.StringNetworkSpecifier", ifName)
}
// EthernetNetworkSpecifier is not part of the SDK in some branches using this utility
@@ -50,4 +50,4 @@
return Class.forName(clazz)
.getConstructor(String::class.java).newInstance(specifier) as NetworkSpecifier
}
-}
\ No newline at end of file
+}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
index 3fcf801..21e84da 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
@@ -18,58 +18,41 @@
import android.os.Build
import androidx.test.InstrumentationRegistry
-import com.android.modules.utils.build.SdkLevel
-import kotlin.test.fail
+import com.android.modules.utils.build.UnboundedSdkLevel
import org.junit.Assume.assumeTrue
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.util.regex.Pattern
-// TODO: Remove it when Build.VERSION_CODES.SC_V2 is available
-const val SC_V2 = 32
+@Deprecated("Use Build.VERSION_CODES", ReplaceWith("Build.VERSION_CODES.S_V2"))
+const val SC_V2 = Build.VERSION_CODES.S_V2
private val MAX_TARGET_SDK_ANNOTATION_RE = Pattern.compile("MaxTargetSdk([0-9]+)$")
private val targetSdk = InstrumentationRegistry.getContext().applicationInfo.targetSdkVersion
+private fun isDevSdkInRange(minExclusive: String?, maxInclusive: String?): Boolean {
+ return (minExclusive == null || !UnboundedSdkLevel.isAtMost(minExclusive)) &&
+ (maxInclusive == null || UnboundedSdkLevel.isAtMost(maxInclusive))
+}
+
/**
- * Returns true if the development SDK version of the device is in the provided range.
+ * Returns true if the development SDK version of the device is in the provided annotation range.
*
- * If the device is not using a release SDK, the development SDK is considered to be higher than
- * [Build.VERSION.SDK_INT].
+ * If the device is not using a release SDK, the development SDK differs from
+ * [Build.VERSION.SDK_INT], and is indicated by the device codenames; see [UnboundedSdkLevel].
*/
-fun isDevSdkInRange(minExclusive: Int?, maxInclusive: Int?): Boolean {
- return (minExclusive == null || isDevSdkAfter(minExclusive)) &&
- (maxInclusive == null || isDevSdkUpTo(maxInclusive))
-}
-
-private fun isDevSdkAfter(minExclusive: Int): Boolean {
- // A development build for T typically has SDK_INT = 30 (R) or SDK_INT = 31 (S), so SDK_INT
- // alone cannot be used to check the SDK version.
- // For recent SDKs that still have development builds used for testing, use SdkLevel utilities
- // instead of SDK_INT.
- return when (minExclusive) {
- // TODO: Use Build.VERSION_CODES.SC_V2 when it is available
- SC_V2 -> SdkLevel.isAtLeastT()
- // TODO: To use SdkLevel.isAtLeastSv2 when available
- Build.VERSION_CODES.S -> fail("Do you expect to ignore the test until T? Use SC_V2 instead")
- Build.VERSION_CODES.R -> SdkLevel.isAtLeastS()
- // Development builds of SDK versions <= R are not used anymore
- else -> Build.VERSION.SDK_INT > minExclusive
- }
-}
-
-private fun isDevSdkUpTo(maxInclusive: Int): Boolean {
- return when (maxInclusive) {
- // TODO: Use Build.VERSION_CODES.SC_V2 when it is available
- SC_V2 -> !SdkLevel.isAtLeastT()
- // TODO: To use SdkLevel.isAtLeastSv2 when available
- Build.VERSION_CODES.S ->
- fail("Do you expect to ignore the test before T? Use SC_V2 instead")
- Build.VERSION_CODES.R -> !SdkLevel.isAtLeastS()
- // Development builds of SDK versions <= R are not used anymore
- else -> Build.VERSION.SDK_INT <= maxInclusive
- }
+fun isDevSdkInRange(
+ ignoreUpTo: DevSdkIgnoreRule.IgnoreUpTo?,
+ ignoreAfter: DevSdkIgnoreRule.IgnoreAfter?
+): Boolean {
+ val minExclusive =
+ if (ignoreUpTo?.value == 0) ignoreUpTo.codename
+ else ignoreUpTo?.value?.toString()
+ val maxInclusive =
+ if (ignoreAfter?.value == 0) ignoreAfter.codename
+ else ignoreAfter?.value?.toString()
+ return isDevSdkInRange(minExclusive, maxInclusive)
}
private fun getMaxTargetSdk(description: Description): Int? {
@@ -86,13 +69,23 @@
* If the device is not using a release SDK, the development SDK is considered to be higher than
* [Build.VERSION.SDK_INT].
*
- * @param ignoreClassUpTo Skip all tests in the class if the device dev SDK is <= this value.
- * @param ignoreClassAfter Skip all tests in the class if the device dev SDK is > this value.
+ * @param ignoreClassUpTo Skip all tests in the class if the device dev SDK is <= this codename or
+ * SDK level.
+ * @param ignoreClassAfter Skip all tests in the class if the device dev SDK is > this codename or
+ * SDK level.
*/
class DevSdkIgnoreRule @JvmOverloads constructor(
- private val ignoreClassUpTo: Int? = null,
- private val ignoreClassAfter: Int? = null
+ private val ignoreClassUpTo: String? = null,
+ private val ignoreClassAfter: String? = null
) : TestRule {
+ /**
+ * @param ignoreClassUpTo Skip all tests in the class if the device dev SDK is <= this value.
+ * @param ignoreClassAfter Skip all tests in the class if the device dev SDK is > this value.
+ */
+ @JvmOverloads
+ constructor(ignoreClassUpTo: Int?, ignoreClassAfter: Int? = null) : this(
+ ignoreClassUpTo?.toString(), ignoreClassAfter?.toString())
+
override fun apply(base: Statement, description: Description): Statement {
return IgnoreBySdkStatement(base, description)
}
@@ -103,7 +96,7 @@
* If the device is not using a release SDK, the development SDK is considered to be higher
* than [Build.VERSION.SDK_INT].
*/
- annotation class IgnoreAfter(val value: Int)
+ annotation class IgnoreAfter(val value: Int = 0, val codename: String = "")
/**
* Ignore the test for any development SDK that lower than or equal to [value].
@@ -111,7 +104,7 @@
* If the device is not using a release SDK, the development SDK is considered to be higher
* than [Build.VERSION.SDK_INT].
*/
- annotation class IgnoreUpTo(val value: Int)
+ annotation class IgnoreUpTo(val value: Int = 0, val codename: String = "")
private inner class IgnoreBySdkStatement(
private val base: Statement,
@@ -124,7 +117,7 @@
val devSdkMessage = "Skipping test for build ${Build.VERSION.CODENAME} " +
"with SDK ${Build.VERSION.SDK_INT}"
assumeTrue(devSdkMessage, isDevSdkInRange(ignoreClassUpTo, ignoreClassAfter))
- assumeTrue(devSdkMessage, isDevSdkInRange(ignoreUpTo?.value, ignoreAfter?.value))
+ assumeTrue(devSdkMessage, isDevSdkInRange(ignoreUpTo, ignoreAfter))
val maxTargetSdk = getMaxTargetSdk(description)
if (maxTargetSdk != null) {
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRunner.kt b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRunner.kt
index da7bf97..2e73666 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRunner.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRunner.kt
@@ -52,7 +52,7 @@
val ignoreAfter = it.getAnnotation(IgnoreAfter::class.java)
val ignoreUpTo = it.getAnnotation(IgnoreUpTo::class.java)
- if (isDevSdkInRange(ignoreUpTo?.value, ignoreAfter?.value)) AndroidJUnit4(klass) else null
+ if (isDevSdkInRange(ignoreUpTo, ignoreAfter)) AndroidJUnit4(klass) else null
}
override fun run(notifier: RunNotifier) {