summaryrefslogtreecommitdiff
path: root/ravenwood/junit-src
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@google.com> 2024-01-25 15:00:04 -0700
committer Jeff Sharkey <jsharkey@google.com> 2024-01-26 10:06:18 -0700
commit1a84549be3841f3ad9844067b8cc590e0a68efad (patch)
treef65e390edd2de64bcfd15adbc7923559bcd51761 /ravenwood/junit-src
parenteb64902270ec6805ad82122ff4b2ff19f2b21cec (diff)
Offer `RavenwoodClassRule`.
Some tests interact with yet-unsupported APIs under Ravenwood in their test class constructors, and `RavenwoodRule` arrives too late to effectively apply annotations like `@IgnoreUnderRavenwood`. This change adds `RavenwoodClassRule` which can be marked as an `@ClassRule` so that it runs in a static context before each test class is constructed, giving it a chance to respect annotations. We also adjust our annotation naming to match the naming style in JUnit Jupiter, which has annotations like `DisabledOnJre` and `EnabledOnOs`. Bug: 319647875 Test: atest SystemUiRoboTests Test: atest SystemUiRavenTests Change-Id: I7d834b8e74e961bb3d4befcad6204d99f8fe80e9
Diffstat (limited to 'ravenwood/junit-src')
-rw-r--r--ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java (renamed from ravenwood/junit-src/android/platform/test/annotations/ExcludeUnderRavenwood.java)13
-rw-r--r--ravenwood/junit-src/android/platform/test/annotations/EnabledOnRavenwood.java (renamed from ravenwood/junit-src/android/platform/test/annotations/IncludeUnderRavenwood.java)13
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java63
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java98
4 files changed, 134 insertions, 53 deletions
diff --git a/ravenwood/junit-src/android/platform/test/annotations/ExcludeUnderRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java
index 2ef381e8682c..4bf09807c360 100644
--- a/ravenwood/junit-src/android/platform/test/annotations/ExcludeUnderRavenwood.java
+++ b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java
@@ -23,15 +23,16 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Tests marked with this annotation are excluded when running under a Ravenwood test environment.
+ * Tests marked with this annotation are disabled when running under a Ravenwood test environment.
*
* A more specific method-level annotation always takes precedence over any class-level
- * annotation, and an {@link IncludeUnderRavenwood} annotation always takes precedence over
- * an {@link ExcludeUnderRavenwood} annotation.
+ * annotation, and an {@link EnabledOnRavenwood} annotation always takes precedence over
+ * an {@link DisabledOnRavenwood} annotation.
*
* This annotation only takes effect when the containing class has a {@code
- * RavenwoodRule} configured. Ignoring is accomplished by throwing an {@code org.junit
- * .AssumptionViolatedException} which test infrastructure treats as being ignored.
+ * RavenwoodRule} or {@code RavenwoodClassRule} configured. Ignoring is accomplished by
+ * throwing an {@code org.junit.AssumptionViolatedException} which test infrastructure treats as
+ * being ignored.
*
* This annotation has no effect on any other non-Ravenwood test environments.
*
@@ -40,5 +41,5 @@ import java.lang.annotation.Target;
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
-public @interface ExcludeUnderRavenwood {
+public @interface DisabledOnRavenwood {
}
diff --git a/ravenwood/junit-src/android/platform/test/annotations/IncludeUnderRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/EnabledOnRavenwood.java
index 0b2e32f67960..9dd0a58a9db1 100644
--- a/ravenwood/junit-src/android/platform/test/annotations/IncludeUnderRavenwood.java
+++ b/ravenwood/junit-src/android/platform/test/annotations/EnabledOnRavenwood.java
@@ -23,15 +23,16 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Tests marked with this annotation are included when running under a Ravenwood test environment.
+ * Tests marked with this annotation are enabled when running under a Ravenwood test environment.
*
* A more specific method-level annotation always takes precedence over any class-level
- * annotation, and an {@link IncludeUnderRavenwood} annotation always takes precedence over
- * an {@link ExcludeUnderRavenwood} annotation.
+ * annotation, and an {@link EnabledOnRavenwood} annotation always takes precedence over
+ * an {@link DisabledOnRavenwood} annotation.
*
* This annotation only takes effect when the containing class has a {@code
- * RavenwoodRule} configured. Ignoring is accomplished by throwing an {@code org.junit
- * .AssumptionViolatedException} which test infrastructure treats as being ignored.
+ * RavenwoodRule} or {@code RavenwoodClassRule} configured. Ignoring is accomplished by
+ * throwing an {@code org.junit.AssumptionViolatedException} which test infrastructure treats as
+ * being ignored.
*
* This annotation has no effect on any other non-Ravenwood test environments.
*
@@ -40,5 +41,5 @@ import java.lang.annotation.Target;
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
-public @interface IncludeUnderRavenwood {
+public @interface EnabledOnRavenwood {
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java
new file mode 100644
index 000000000000..68b163ede89c
--- /dev/null
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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 android.platform.test.ravenwood;
+
+import static android.platform.test.ravenwood.RavenwoodRule.ENABLE_PROBE_IGNORED;
+import static android.platform.test.ravenwood.RavenwoodRule.IS_ON_RAVENWOOD;
+import static android.platform.test.ravenwood.RavenwoodRule.shouldEnableOnRavenwood;
+
+import android.platform.test.annotations.DisabledOnRavenwood;
+import android.platform.test.annotations.EnabledOnRavenwood;
+
+import org.junit.Assume;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * {@code @ClassRule} that respects Ravenwood-specific class annotations. This rule has no effect
+ * when tests are run on non-Ravenwood test environments.
+ *
+ * By default, all tests are executed on Ravenwood, but annotations such as
+ * {@link DisabledOnRavenwood} and {@link EnabledOnRavenwood} can be used at both the method
+ * and class level to "ignore" tests that may not be ready.
+ */
+public class RavenwoodClassRule implements TestRule {
+ @Override
+ public Statement apply(Statement base, Description description) {
+ // No special treatment when running outside Ravenwood; run tests as-is
+ if (!IS_ON_RAVENWOOD) {
+ return base;
+ }
+
+ if (ENABLE_PROBE_IGNORED) {
+ // Pass through to possible underlying RavenwoodRule for both environment
+ // configuration and handling method-level annotations
+ return base;
+ } else {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ Assume.assumeTrue(shouldEnableOnRavenwood(description));
+ // Pass through to possible underlying RavenwoodRule for both environment
+ // configuration and handling method-level annotations
+ base.evaluate();
+ }
+ };
+ }
+ }
+}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index dd442f08321f..fef77f9d5ed7 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -18,9 +18,9 @@ package android.platform.test.ravenwood;
import static org.junit.Assert.fail;
-import android.platform.test.annotations.ExcludeUnderRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.IgnoreUnderRavenwood;
-import android.platform.test.annotations.IncludeUnderRavenwood;
+import android.platform.test.annotations.EnabledOnRavenwood;
import org.junit.Assume;
import org.junit.rules.TestRule;
@@ -30,29 +30,36 @@ import org.junit.runners.model.Statement;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * THIS RULE IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
- * QUESTIONS ABOUT IT.
+ * {@code @Rule} that configures the Ravenwood test environment. This rule has no effect when
+ * tests are run on non-Ravenwood test environments.
*
- * @hide
+ * This rule initializes and resets the Ravenwood environment between each test method to offer a
+ * hermetic testing environment.
+ *
+ * By default, all tests are executed on Ravenwood, but annotations such as
+ * {@link DisabledOnRavenwood} and {@link EnabledOnRavenwood} can be used at both the method
+ * and class level to "ignore" tests that may not be ready. When needed, a
+ * {@link RavenwoodClassRule} can be used in addition to a {@link RavenwoodRule} to ignore tests
+ * before a test class is fully initialized.
*/
public class RavenwoodRule implements TestRule {
- private static AtomicInteger sNextPid = new AtomicInteger(100);
-
- private static final boolean IS_UNDER_RAVENWOOD = RavenwoodRuleImpl.isUnderRavenwood();
+ static final boolean IS_ON_RAVENWOOD = RavenwoodRuleImpl.isOnRavenwood();
/**
- * When probing is enabled, all tests will be unconditionally run under Ravenwood to detect
+ * When probing is enabled, all tests will be unconditionally run on Ravenwood to detect
* cases where a test is able to pass despite being marked as {@code IgnoreUnderRavenwood}.
*
* This is typically helpful for internal maintainers discovering tests that had previously
* been ignored, but now have enough Ravenwood-supported functionality to be enabled.
*/
- private static final boolean ENABLE_PROBE_IGNORED = false; // DO NOT SUBMIT WITH TRUE
+ static final boolean ENABLE_PROBE_IGNORED = false; // DO NOT SUBMIT WITH TRUE
private static final int SYSTEM_UID = 1000;
private static final int NOBODY_UID = 9999;
private static final int FIRST_APPLICATION_UID = 10000;
+ private static final AtomicInteger sNextPid = new AtomicInteger(100);
+
/**
* Unless the test author requests differently, run as "nobody", and give each collection of
* tests its own unique PID.
@@ -75,7 +82,7 @@ public class RavenwoodRule implements TestRule {
/**
* Configure the identity of this process to be the system UID for the duration of the
- * test. Has no effect under non-Ravenwood environments.
+ * test. Has no effect on non-Ravenwood environments.
*/
public Builder setProcessSystem() {
mRule.mUid = SYSTEM_UID;
@@ -84,7 +91,7 @@ public class RavenwoodRule implements TestRule {
/**
* Configure the identity of this process to be an app UID for the duration of the
- * test. Has no effect under non-Ravenwood environments.
+ * test. Has no effect on non-Ravenwood environments.
*/
public Builder setProcessApp() {
mRule.mUid = FIRST_APPLICATION_UID;
@@ -93,7 +100,7 @@ public class RavenwoodRule implements TestRule {
/**
* Configure a "main" thread to be available for the duration of the test, as defined
- * by {@code Looper.getMainLooper()}. Has no effect under non-Ravenwood environments.
+ * by {@code Looper.getMainLooper()}. Has no effect on non-Ravenwood environments.
*/
public Builder setProvideMainThread(boolean provideMainThread) {
mRule.mProvideMainThread = provideMainThread;
@@ -108,7 +115,7 @@ public class RavenwoodRule implements TestRule {
* All properties in the {@code debug.*} namespace are automatically mutable, with no
* developer action required.
*
- * Has no effect under non-Ravenwood environments.
+ * Has no effect on non-Ravenwood environments.
*/
public Builder setSystemPropertyImmutable(/* @NonNull */ String key,
/* @Nullable */ Object value) {
@@ -125,7 +132,7 @@ public class RavenwoodRule implements TestRule {
* All properties in the {@code debug.*} namespace are automatically mutable, with no
* developer action required.
*
- * Has no effect under non-Ravenwood environments.
+ * Has no effect on non-Ravenwood environments.
*/
public Builder setSystemPropertyMutable(/* @NonNull */ String key,
/* @Nullable */ Object value) {
@@ -140,42 +147,51 @@ public class RavenwoodRule implements TestRule {
}
/**
- * Return if the current process is running under a Ravenwood test environment.
+ * @deprecated replaced by {@link #isOnRavenwood()}
*/
+ @Deprecated
public static boolean isUnderRavenwood() {
- return IS_UNDER_RAVENWOOD;
+ return IS_ON_RAVENWOOD;
+ }
+
+ /**
+ * Return if the current process is running on a Ravenwood test environment.
+ */
+ public static boolean isOnRavenwood() {
+ return IS_ON_RAVENWOOD;
}
/**
- * Determine if the given {@link Description} should be included when running under the
+ * Determine if the given {@link Description} should be enabled when running on the
* Ravenwood test environment.
*
* A more specific method-level annotation always takes precedence over any class-level
- * annotation, and an {@link IncludeUnderRavenwood} annotation always takes precedence over
- * an {@link ExcludeUnderRavenwood} annotation.
+ * annotation, and an {@link EnabledOnRavenwood} annotation always takes precedence over
+ * an {@link DisabledOnRavenwood} annotation.
*/
- private boolean shouldIncludeUnderRavenwood(Description description) {
- // Stopgap for http://g/ravenwood/EPAD-N5ntxM
- if (description.getMethodName().endsWith("$noRavenwood")) {
- return false;
- }
-
+ static boolean shouldEnableOnRavenwood(Description description) {
// First, consult any method-level annotations
- if (description.getAnnotation(IncludeUnderRavenwood.class) != null) {
- return true;
- }
- if (description.getAnnotation(ExcludeUnderRavenwood.class) != null) {
- return false;
- }
- if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) {
- return false;
+ if (description.isTest()) {
+ // Stopgap for http://g/ravenwood/EPAD-N5ntxM
+ if (description.getMethodName().endsWith("$noRavenwood")) {
+ return false;
+ }
+ if (description.getAnnotation(EnabledOnRavenwood.class) != null) {
+ return true;
+ }
+ if (description.getAnnotation(DisabledOnRavenwood.class) != null) {
+ return false;
+ }
+ if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) {
+ return false;
+ }
}
// Otherwise, consult any class-level annotations
- if (description.getTestClass().getAnnotation(IncludeUnderRavenwood.class) != null) {
+ if (description.getTestClass().getAnnotation(EnabledOnRavenwood.class) != null) {
return true;
}
- if (description.getTestClass().getAnnotation(ExcludeUnderRavenwood.class) != null) {
+ if (description.getTestClass().getAnnotation(DisabledOnRavenwood.class) != null) {
return false;
}
if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
@@ -189,7 +205,7 @@ public class RavenwoodRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
// No special treatment when running outside Ravenwood; run tests as-is
- if (!IS_UNDER_RAVENWOOD) {
+ if (!IS_ON_RAVENWOOD) {
return base;
}
@@ -207,7 +223,7 @@ public class RavenwoodRule implements TestRule {
return new Statement() {
@Override
public void evaluate() throws Throwable {
- Assume.assumeTrue(shouldIncludeUnderRavenwood(description));
+ Assume.assumeTrue(shouldEnableOnRavenwood(description));
RavenwoodRuleImpl.init(RavenwoodRule.this);
try {
@@ -221,7 +237,7 @@ public class RavenwoodRule implements TestRule {
/**
* Run the given {@link Statement} with probing enabled. All tests will be unconditionally
- * run under Ravenwood to detect cases where a test is able to pass despite being marked as
+ * run on Ravenwood to detect cases where a test is able to pass despite being marked as
* {@code IgnoreUnderRavenwood}.
*/
private Statement applyProbeIgnored(Statement base, Description description) {
@@ -234,13 +250,13 @@ public class RavenwoodRule implements TestRule {
} catch (Throwable t) {
// If the test isn't included, eat the exception and report the
// assumption failure that test authors expect; otherwise throw
- Assume.assumeTrue(shouldIncludeUnderRavenwood(description));
+ Assume.assumeTrue(shouldEnableOnRavenwood(description));
throw t;
} finally {
RavenwoodRuleImpl.reset(RavenwoodRule.this);
}
- if (!shouldIncludeUnderRavenwood(description)) {
+ if (!shouldEnableOnRavenwood(description)) {
fail("Test wasn't included under Ravenwood, but it actually "
+ "passed under Ravenwood; consider updating annotations");
}