1 /* 2 * Copyright (C) 2017 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 com.android.tradefed.util; 18 19 import com.android.tradefed.build.IBuildInfo; 20 import com.android.tradefed.build.IDeviceBuildInfo; 21 import com.android.tradefed.log.LogUtil.CLog; 22 23 import com.google.common.annotations.VisibleForTesting; 24 25 import java.io.File; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 33 /** Utility class for making system calls. */ 34 public class SystemUtil { 35 36 @VisibleForTesting static SystemUtil singleton = new SystemUtil(); 37 38 // Environment variables for the test cases directory in target out directory and host out 39 // directory. 40 public enum EnvVariable { 41 ANDROID_TARGET_OUT_TESTCASES, 42 ANDROID_HOST_OUT_TESTCASES, 43 } 44 45 public static final String REMOTE_VM_VARIABLE = "REMOTE_VM_ENV"; 46 47 private static final String HOST_TESTCASES = "host/testcases"; 48 private static final String TARGET_TESTCASES = "target/testcases"; 49 50 /** Keep track of the mapping of the variables to the subpath it takes in the tests dir. */ 51 public static final Map<EnvVariable, String> ENV_VARIABLE_PATHS_IN_TESTS_DIR = new HashMap<>(); 52 53 static { ENV_VARIABLE_PATHS_IN_TESTS_DIR.put( EnvVariable.ANDROID_TARGET_OUT_TESTCASES, TARGET_TESTCASES)54 ENV_VARIABLE_PATHS_IN_TESTS_DIR.put( 55 EnvVariable.ANDROID_TARGET_OUT_TESTCASES, TARGET_TESTCASES); ENV_VARIABLE_PATHS_IN_TESTS_DIR.put(EnvVariable.ANDROID_HOST_OUT_TESTCASES, HOST_TESTCASES)56 ENV_VARIABLE_PATHS_IN_TESTS_DIR.put(EnvVariable.ANDROID_HOST_OUT_TESTCASES, HOST_TESTCASES); 57 } 58 59 static final String ENV_ANDROID_PRODUCT_OUT = "ANDROID_PRODUCT_OUT"; 60 61 62 /** 63 * Get the value of an environment variable. 64 * 65 * <p>The wrapper function is created for mock in unit test. 66 * 67 * @param name the name of the environment variable. 68 * @return {@link String} value of the given environment variable. 69 */ 70 @VisibleForTesting getEnv(String name)71 String getEnv(String name) { 72 return System.getenv(name); 73 } 74 75 /** Get a list of {@link File} pointing to tests directories external to Tradefed. */ getExternalTestCasesDirs()76 public static List<File> getExternalTestCasesDirs() { 77 List<File> testCasesDirs = new ArrayList<File>(); 78 // TODO(b/36782030): Support running both HOST and TARGET tests. 79 List<String> testCasesDirNames = 80 // List order matters. ConfigurationFactory caller uses first dir with test config. 81 Arrays.asList( 82 singleton.getEnv(EnvVariable.ANDROID_TARGET_OUT_TESTCASES.name()), 83 singleton.getEnv(EnvVariable.ANDROID_HOST_OUT_TESTCASES.name())); 84 for (String testCasesDirName : testCasesDirNames) { 85 if (testCasesDirName != null) { 86 File dir = new File(testCasesDirName); 87 if (dir.exists() && dir.isDirectory()) { 88 CLog.d("Found test case dir: %s", testCasesDirName); 89 testCasesDirs.add(dir); 90 } else { 91 CLog.w( 92 "Path %s for test cases directory does not exist or it's not a " 93 + "directory.", 94 testCasesDirName); 95 } 96 } 97 } 98 return testCasesDirs; 99 } 100 101 /** 102 * Get the file associated with the env. variable. 103 * 104 * @param envVariable ANDROID_TARGET_OUT_TESTCASES or ANDROID_HOST_OUT_TESTCASES 105 * @return The directory associated. 106 */ getExternalTestCasesDir(EnvVariable envVariable)107 public static File getExternalTestCasesDir(EnvVariable envVariable) { 108 String var = System.getenv(envVariable.name()); 109 if (var == null) { 110 return null; 111 } 112 File dir = new File(var); 113 if (dir.exists() && dir.isDirectory()) { 114 CLog.d("Found test case dir: %s for %s.", dir.getAbsolutePath(), envVariable.name()); 115 return dir; 116 } 117 return null; 118 } 119 120 /** 121 * Get a list of {@link File} of the test cases directories 122 * 123 * @param buildInfo the build artifact information. Set it to null if build info is not 124 * available or there is no need to get test cases directories from build info. 125 * @return a list of {@link File} of directories of the test cases folder of build output, based 126 * on the value of environment variables and the given build info. 127 */ getTestCasesDirs(IBuildInfo buildInfo)128 public static List<File> getTestCasesDirs(IBuildInfo buildInfo) { 129 List<File> testCasesDirs = new ArrayList<File>(); 130 testCasesDirs.addAll(getExternalTestCasesDirs()); 131 132 // TODO: Remove this logic after Versioned TF V2 is implemented, in which staging build 133 // artifact will be done by the parent process, and the test cases dirs will be set by 134 // environment variables. 135 // Add tests dir from build info. 136 if (buildInfo instanceof IDeviceBuildInfo) { 137 IDeviceBuildInfo deviceBuildInfo = (IDeviceBuildInfo) buildInfo; 138 File testsDir = deviceBuildInfo.getTestsDir(); 139 // Add all possible paths to the testcases directory list. 140 if (testsDir != null) { 141 testCasesDirs.addAll( 142 Arrays.asList( 143 testsDir, 144 FileUtil.getFileForPath(testsDir, HOST_TESTCASES), 145 FileUtil.getFileForPath(testsDir, TARGET_TESTCASES))); 146 } 147 } 148 149 return testCasesDirs; 150 } 151 152 /** 153 * Gets the product specific output dir from an Android build tree. Typically this location 154 * contains images for various device partitions, bootloader, radio and so on. 155 * 156 * <p>Note: the method does not guarantee that this path exists. 157 * 158 * @return the location of the output dir or <code>null</code> if the current build is not 159 */ getProductOutputDir()160 public static File getProductOutputDir() { 161 String path = singleton.getEnv(ENV_ANDROID_PRODUCT_OUT); 162 if (path == null) { 163 return null; 164 } else { 165 return new File(path); 166 } 167 } 168 169 /** Return true if we are currently running in a remote environment. */ isRemoteEnvironment()170 public static boolean isRemoteEnvironment() { 171 if ("1".equals(System.getenv(REMOTE_VM_VARIABLE))) { 172 return true; 173 } 174 return false; 175 } 176 177 /** Returns the path to the Java binary that current test harness is running in */ getRunningJavaBinaryPath()178 public static File getRunningJavaBinaryPath() { 179 String javaHome = System.getProperty("java.home"); 180 if (javaHome == null) { 181 throw new RuntimeException("System property \"java.home\" is not set."); 182 } 183 // this only works on *nix systems, but it's not like we officially support any others 184 File javaBinary = new File(String.format("%s/bin/java", javaHome)); 185 if (!javaBinary.exists()) { 186 throw new RuntimeException( 187 String.format("Computed Java binary path %s does not exist", javaBinary)); 188 } 189 return javaBinary; 190 } 191 } 192