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 android.content.pm.PackageManager; 21 import android.os.Build; 22 import android.util.Log; 23 24 import androidx.test.InstrumentationRegistry; 25 import androidx.test.uiautomator.UiDevice; 26 27 import org.junit.rules.TestRule; 28 import org.junit.runner.Description; 29 import org.junit.runners.model.Statement; 30 31 import java.lang.annotation.ElementType; 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.lang.annotation.Target; 35 import java.util.regex.Matcher; 36 import java.util.regex.Pattern; 37 38 public class TestStabilityRule implements TestRule { 39 private static final String TAG = "TestStabilityRule"; 40 private static final Pattern LAUNCHER_BUILD = 41 Pattern.compile("^(" 42 + "(?<local>(BuildFromAndroidStudio|" 43 + "([0-9]+|[A-Z])-eng\\.[a-z]+\\.[0-9]+\\.[0-9]+))|" 44 + "(?<platform>([A-Z][a-z]*[0-9]*|[0-9]+)*)" 45 + ")$"); 46 private static final Pattern PLATFORM_BUILD = 47 Pattern.compile("^(" 48 + "(?<commandLine>eng\\.[a-z]+\\.[0-9]+\\.[0-9]+)|" 49 + "(?<presubmit>P[0-9]+)|" 50 + "(?<postsubmit>[0-9]+)" 51 + ")$"); 52 53 public static final int LOCAL = 0x1; 54 public static final int PLATFORM_PRESUBMIT = 0x8; 55 public static final int PLATFORM_POSTSUBMIT = 0x10; 56 57 private static int sRunFlavor; 58 59 @Retention(RetentionPolicy.RUNTIME) 60 @Target(ElementType.METHOD) 61 public @interface Stability { flavors()62 int flavors(); 63 } 64 65 @Override apply(Statement base, Description description)66 public Statement apply(Statement base, Description description) { 67 final Stability stability = description.getAnnotation(Stability.class); 68 if (stability != null) { 69 return new Statement() { 70 @Override 71 public void evaluate() throws Throwable { 72 if ((stability.flavors() & getRunFlavor()) != 0) { 73 Log.d(TAG, "Running " + description.getDisplayName()); 74 base.evaluate(); 75 } else { 76 Log.d(TAG, "Skipping " + description.getDisplayName()); 77 } 78 } 79 }; 80 } else { 81 return base; 82 } 83 } 84 85 public static int getRunFlavor() { 86 if (sRunFlavor != 0) return sRunFlavor; 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