Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7acaa5f3 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "`RavenwoodRule` opt-in and opt-out support." into main

parents d8693af7 c194caa7
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
/*
 * 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.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Tests marked with this annotation are excluded 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.
 *
 * 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.
 *
 * This annotation has no effect on any other non-Ravenwood test environments.
 *
 * @hide
 */
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcludeUnderRavenwood {
}
+44 −0
Original line number Diff line number Diff line
/*
 * 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.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Tests marked with this annotation are included 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.
 *
 * 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.
 *
 * This annotation has no effect on any other non-Ravenwood test environments.
 *
 * @hide
 */
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IncludeUnderRavenwood {
}
+46 −22
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package android.platform.test.ravenwood;

import static org.junit.Assert.fail;

import android.platform.test.annotations.ExcludeUnderRavenwood;
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.annotations.IncludeUnderRavenwood;

import org.junit.Assume;
import org.junit.rules.TestRule;
@@ -109,21 +111,52 @@ public class RavenwoodRule implements TestRule {
    }

    /**
     * Test if the given {@link Description} has been marked with an {@link IgnoreUnderRavenwood}
     * annotation, either at the method or class level.
     * Determine if the given {@link Description} should be included when running under 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.
     */
    private static boolean hasIgnoreUnderRavenwoodAnnotation(Description description) {
        if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
    private boolean shouldIncludeUnderRavenwood(Description description) {
        // Stopgap for http://g/ravenwood/EPAD-N5ntxM
        if (description.getMethodName().endsWith("$noRavenwood")) {
            return false;
        }

        // First, consult any method-level annotations
        if (description.getAnnotation(IncludeUnderRavenwood.class) != null) {
            return true;
        } else if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) {
        }
        if (description.getAnnotation(ExcludeUnderRavenwood.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) {
            return true;
        } else {
        }
        if (description.getTestClass().getAnnotation(ExcludeUnderRavenwood.class) != null) {
            return false;
        }
        if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
            return false;
        }

        // When no annotations have been requested, assume test should be included
        return true;
    }

    @Override
    public Statement apply(Statement base, Description description) {
        // No special treatment when running outside Ravenwood; run tests as-is
        if (!IS_UNDER_RAVENWOOD) {
            return base;
        }

        if (ENABLE_PROBE_IGNORED) {
            return applyProbeIgnored(base, description);
        } else {
@@ -138,14 +171,7 @@ public class RavenwoodRule implements TestRule {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                if (hasIgnoreUnderRavenwoodAnnotation(description)) {
                    Assume.assumeFalse(IS_UNDER_RAVENWOOD);
                }

                // Stopgap for http://g/ravenwood/EPAD-N5ntxM
                if (description.getMethodName().endsWith("$noRavenwood")) {
                    Assume.assumeFalse(IS_UNDER_RAVENWOOD);
                }
                Assume.assumeTrue(shouldIncludeUnderRavenwood(description));

                RavenwoodRuleImpl.init(RavenwoodRule.this);
                try {
@@ -170,19 +196,17 @@ public class RavenwoodRule implements TestRule {
                try {
                    base.evaluate();
                } catch (Throwable t) {
                    if (hasIgnoreUnderRavenwoodAnnotation(description)) {
                        // This failure is expected, so eat the exception and report the
                        // assumption failure that test authors expect
                        Assume.assumeFalse(IS_UNDER_RAVENWOOD);
                    }
                    // If the test isn't included, eat the exception and report the
                    // assumption failure that test authors expect; otherwise throw
                    Assume.assumeTrue(shouldIncludeUnderRavenwood(description));
                    throw t;
                } finally {
                    RavenwoodRuleImpl.reset(RavenwoodRule.this);
                }

                if (hasIgnoreUnderRavenwoodAnnotation(description) && IS_UNDER_RAVENWOOD) {
                    fail("Test was annotated with IgnoreUnderRavenwood, but it actually "
                            + "passed under Ravenwood; consider removing the annotation");
                if (!shouldIncludeUnderRavenwood(description)) {
                    fail("Test wasn't included under Ravenwood, but it actually "
                            + "passed under Ravenwood; consider updating annotations");
                }
            }
        };