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 import androidx.test.platform.app.InstrumentationRegistry; 20 import androidx.test.uiautomator.UiDevice; 21 22 import org.junit.AssumptionViolatedException; 23 import org.junit.rules.TestRule; 24 import org.junit.runner.Description; 25 import org.junit.runners.model.Statement; 26 27 import java.io.IOException; 28 import java.lang.annotation.ElementType; 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.lang.annotation.Target; 32 import java.util.Arrays; 33 34 /** 35 * Rule that runs tests marked with @Presubmit on presubmit test runs, only on devices listed in the 36 * comma-separated string passed as an argument to the @Presubmit annotation. The test will be 37 * skipped, for presubmit runs, on devices not in the list. 38 */ 39 public class PresubmitRule implements TestRule { runningInPresubmit()40 public static boolean runningInPresubmit() { 41 // We run in presubmit when there is a parameter to exclude postsubmits. 42 final String nonAnnotationArgument = 43 InstrumentationRegistry.getArguments().getString("notAnnotation", ""); 44 return Arrays.stream(nonAnnotationArgument.split(",")) 45 .anyMatch("android.platform.test.annotations.Postsubmit"::equals); 46 } 47 48 @Override apply(Statement base, Description description)49 public Statement apply(Statement base, Description description) { 50 // If the test is not annotated with @Presubmit, this rule is not applicable. 51 final Presubmit annotation = description.getTestClass().getAnnotation(Presubmit.class); 52 if (annotation == null) return base; 53 54 // If the test suite isn't running with 55 // "exclude-annotation": "android.platform.test.annotations.Postsubmit", then this is not 56 // a presubmit test, and the rule is not applicable. 57 if (!runningInPresubmit()) { 58 return base; 59 } 60 61 final String flavor; 62 try { 63 flavor = 64 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) 65 .executeShellCommand("getprop ro.build.flavor") 66 .replaceAll("\\s", "") 67 .replace("-userdebug", ""); 68 } catch (IOException e) { 69 throw new RuntimeException(e); 70 } 71 72 // If the target IS listed in the annotation's parameter, this rule is not applicable. 73 final boolean match = Arrays.asList(annotation.value().split(",")).contains(flavor); 74 if (match) return base; 75 76 // The test will be skipped upon start. 77 return new Statement() { 78 @Override 79 public void evaluate() throws Throwable { 80 throw new AssumptionViolatedException( 81 "Skipping the test on target " 82 + flavor 83 + " which in not in " 84 + annotation.value()); 85 } 86 }; 87 } 88 89 @Retention(RetentionPolicy.RUNTIME) 90 @Target({ElementType.TYPE}) 91 public @interface Presubmit { 92 String value(); 93 } 94 } 95