• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.platform.test.rule;
18 
19 
20 import androidx.test.platform.app.InstrumentationRegistry;
21 import androidx.test.uiautomator.UiDevice;
22 
23 import org.junit.AssumptionViolatedException;
24 import org.junit.rules.TestRule;
25 import org.junit.runner.Description;
26 import org.junit.runners.model.Statement;
27 
28 import java.io.IOException;
29 import java.lang.annotation.ElementType;
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.lang.annotation.Target;
33 import java.util.Arrays;
34 
35 /**
36  * Rule that runs tests marked with @Presubmit on presubmit test runs, only on devices listed in the
37  * comma-separated string passed as an argument to the @Presubmit annotation. The test will be
38  * skipped, for presubmit runs, on devices not in the list.
39  */
40 public class PresubmitRule implements TestRule {
41 
42     /**
43      * For test running in config that implements the instrumentation argument is-presubmit (such as
44      * cl/663453103), return true if the test is actually running in presubmit.
45      *
46      * <p>Otherwise, return true if there is a parameter to exclude postsubmit.
47      */
runningInPresubmit()48     public static boolean runningInPresubmit() {
49         final String isPresubmit =
50                 InstrumentationRegistry.getArguments().getString("is-presubmit", "unknown");
51         if (isPresubmit.equals("true")) {
52             return true;
53         } else if (isPresubmit.equals("false")) {
54             return false;
55         }
56 
57         // We run in presubmit when there is a parameter to exclude postsubmits.
58         final String nonAnnotationArgument =
59                 InstrumentationRegistry.getArguments().getString("notAnnotation", "");
60         return Arrays.asList(nonAnnotationArgument.split(","))
61                 .contains("android.platform.test.annotations.Postsubmit");
62     }
63 
64     @Override
apply(Statement base, Description description)65     public Statement apply(Statement base, Description description) {
66         // If the test is not annotated with @Presubmit, this rule is not applicable.
67         final Presubmit annotation = description.getTestClass().getAnnotation(Presubmit.class);
68         if (annotation == null) return base;
69 
70         // If the test suite isn't running with
71         // "exclude-annotation": "android.platform.test.annotations.Postsubmit", then this is not
72         // a presubmit test, and the rule is not applicable.
73         if (!runningInPresubmit()) {
74             return base;
75         }
76 
77         final String flavor;
78         try {
79             flavor =
80                     UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
81                             .executeShellCommand("getprop ro.build.flavor")
82                             .replaceAll("\\s", "")
83                             .replace("-userdebug", "");
84         } catch (IOException e) {
85             throw new RuntimeException(e);
86         }
87 
88         // If the target IS listed in the annotation's parameter, this rule is not applicable.
89         final boolean match = Arrays.asList(annotation.value().split(",")).contains(flavor);
90         if (match) return base;
91 
92         // The test will be skipped upon start.
93         return new Statement() {
94             @Override
95             public void evaluate() throws Throwable {
96                 throw new AssumptionViolatedException(
97                         "Skipping the test on target "
98                                 + flavor
99                                 + " which in not in "
100                                 + annotation.value());
101             }
102         };
103     }
104 
105     @Retention(RetentionPolicy.RUNTIME)
106     @Target({ElementType.TYPE})
107     public @interface Presubmit {
108         String value();
109     }
110 }
111