1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.android.launcher3.util.rule; 17 18 import static androidx.test.InstrumentationRegistry.getInstrumentation; 19 20 import static org.junit.Assume.assumeTrue; 21 22 import android.content.pm.PackageManager; 23 import android.os.Build; 24 import android.util.Log; 25 26 import androidx.test.InstrumentationRegistry; 27 import androidx.test.uiautomator.UiDevice; 28 29 import org.junit.rules.TestRule; 30 import org.junit.runner.Description; 31 import org.junit.runners.model.Statement; 32 33 import java.lang.annotation.ElementType; 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 import java.lang.annotation.Target; 37 import java.util.regex.Matcher; 38 import java.util.regex.Pattern; 39 40 public class TestStabilityRule implements TestRule { 41 private static final String TAG = "TestStabilityRule"; 42 private static final Pattern LAUNCHER_BUILD = 43 Pattern.compile("^(" 44 + "(?<local>(BuildFromAndroidStudio|" 45 + "([0-9]+|[A-Z])-eng\\.[a-z]+\\.[0-9]+\\.[0-9]+))|" 46 + "(?<platform>([A-Z][a-z]*[0-9]*|[0-9]+)*)" 47 + ")$"); 48 private static final Pattern PLATFORM_BUILD = 49 Pattern.compile("^(" 50 + "(?<commandLine>eng\\.[a-z]+\\.[0-9]+\\.[0-9]+)|" 51 + "(?<presubmit>P[0-9]+)|" 52 + "(?<postsubmit>[0-9]+)" 53 + ")$"); 54 55 public static final int LOCAL = 0x1; 56 public static final int PLATFORM_PRESUBMIT = 0x8; 57 public static final int PLATFORM_POSTSUBMIT = 0x10; 58 59 private static int sRunFlavor; 60 61 @Retention(RetentionPolicy.RUNTIME) 62 @Target(ElementType.METHOD) 63 public @interface Stability { flavors()64 int flavors(); 65 } 66 67 @Override apply(Statement base, Description description)68 public Statement apply(Statement base, Description description) { 69 final Stability stability = description.getAnnotation(Stability.class); 70 if (stability != null) { 71 return new Statement() { 72 @Override 73 public void evaluate() throws Throwable { 74 assumeTrue("Ignoring the test due to @Stability annotation", 75 (stability.flavors() & getRunFlavor()) != 0); 76 base.evaluate(); 77 } 78 }; 79 } else { 80 return base; 81 } 82 } 83 84 public static int getRunFlavor() { 85 if (sRunFlavor != 0) return sRunFlavor; 86 if (isRobolectricTest()) return PLATFORM_POSTSUBMIT; 87 88 final String flavorOverride = InstrumentationRegistry.getArguments().getString("flavor"); 89 90 if (flavorOverride != null) { 91 Log.d(TAG, "Flavor override: " + flavorOverride); 92 try { 93 return (int) TestStabilityRule.class.getField(flavorOverride).get(null); 94 } catch (NoSuchFieldException e) { 95 throw new AssertionError("Unrecognized run flavor override: " + flavorOverride); 96 } catch (IllegalAccessException e) { 97 throw new RuntimeException(e); 98 } 99 } 100 101 final String launcherVersion; 102 try { 103 final String launcherPackageName = UiDevice.getInstance(getInstrumentation()) 104 .getLauncherPackageName(); 105 Log.d(TAG, "Launcher package: " + launcherPackageName); 106 107 launcherVersion = getInstrumentation(). 108 getContext(). 109 getPackageManager(). 110 getPackageInfo(launcherPackageName, 0) 111 .versionName; 112 } catch (PackageManager.NameNotFoundException e) { 113 throw new RuntimeException(e); 114 } 115 116 final String platformVersion = Build.VERSION.INCREMENTAL; 117 118 Log.d(TAG, "Launcher: " + launcherVersion + ", platform: " + platformVersion); 119 120 final Matcher launcherBuildMatcher = LAUNCHER_BUILD.matcher(launcherVersion); 121 if (!launcherBuildMatcher.find()) { 122 throw new AssertionError("Launcher build match not found"); 123 } 124 125 final Matcher platformBuildMatcher = PLATFORM_BUILD.matcher(platformVersion); 126 if (!platformBuildMatcher.find()) { 127 throw new AssertionError("Platform build match not found"); 128 } 129 130 if (launcherBuildMatcher.group("local") != null && ( 131 platformBuildMatcher.group("commandLine") != null || 132 platformBuildMatcher.group("postsubmit") != null)) { 133 Log.d(TAG, "LOCAL RUN"); 134 sRunFlavor = LOCAL; 135 } else if (launcherBuildMatcher.group("platform") != null 136 && platformBuildMatcher.group("presubmit") != null) { 137 Log.d(TAG, "PLATFORM PRESUBMIT"); 138 sRunFlavor = PLATFORM_PRESUBMIT; 139 } else if (launcherBuildMatcher.group("platform") != null 140 && (platformBuildMatcher.group("postsubmit") != null 141 || platformBuildMatcher.group("commandLine") != null)) { 142 Log.d(TAG, "PLATFORM POSTSUBMIT"); 143 sRunFlavor = PLATFORM_POSTSUBMIT; 144 } else { 145 throw new AssertionError("Unrecognized run flavor"); 146 } 147 148 return sRunFlavor; 149 } 150 151 public static boolean isPresubmit() { 152 return getRunFlavor() == PLATFORM_PRESUBMIT; 153 } 154 155 public static boolean isRobolectricTest() { 156 return Build.FINGERPRINT.contains("robolectric"); 157 } 158 } 159