1 /* 2 * Copyright (C) 2015 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 package com.android.compatibility.common.tradefed.build; 17 18 import com.android.compatibility.SuiteInfo; 19 import com.android.tradefed.build.IBuildInfo; 20 import com.android.tradefed.build.IFolderBuildInfo; 21 22 import java.io.File; 23 import java.io.FileNotFoundException; 24 import java.text.SimpleDateFormat; 25 import java.util.Date; 26 import java.util.HashMap; 27 import java.util.Map; 28 29 /** 30 * A simple helper that stores and retrieves information from a {@link IBuildInfo}. 31 */ 32 public class CompatibilityBuildHelper { 33 34 public static final String MODULE_IDS = "MODULE_IDS"; 35 36 private static final String ROOT_DIR = "ROOT_DIR"; 37 private static final String ROOT_DIR2 = "ROOT_DIR2"; 38 private static final String SUITE_BUILD = "SUITE_BUILD"; 39 private static final String SUITE_NAME = "SUITE_NAME"; 40 private static final String SUITE_FULL_NAME = "SUITE_FULL_NAME"; 41 private static final String SUITE_VERSION = "SUITE_VERSION"; 42 private static final String SUITE_PLAN = "SUITE_PLAN"; 43 private static final String RESULT_DIR = "RESULT_DIR"; 44 private static final String START_TIME_MS = "START_TIME_MS"; 45 private static final String CONFIG_PATH_PREFIX = "DYNAMIC_CONFIG_FILE:"; 46 private static final String DYNAMIC_CONFIG_OVERRIDE_URL = "DYNAMIC_CONFIG_OVERRIDE_URL"; 47 private static final String COMMAND_LINE_ARGS = "command_line_args"; 48 private static final String RETRY_COMMAND_LINE_ARGS = "retry_command_line_args"; 49 private final IBuildInfo mBuildInfo; 50 private boolean mInitialized = false; 51 52 /** 53 * Creates a {@link CompatibilityBuildHelper} wrapping the given {@link IBuildInfo}. 54 */ CompatibilityBuildHelper(IBuildInfo buildInfo)55 public CompatibilityBuildHelper(IBuildInfo buildInfo) { 56 mBuildInfo = buildInfo; 57 } 58 59 /** 60 * Initializes the {@link IBuildInfo} from the manifest with the current time 61 * as the start time. 62 */ init(String suitePlan, String dynamicConfigUrl)63 public void init(String suitePlan, String dynamicConfigUrl) { 64 init(suitePlan, dynamicConfigUrl, System.currentTimeMillis()); 65 } 66 67 /** 68 * Initializes the {@link IBuildInfo} from the manifest. 69 */ init(String suitePlan, String dynamicConfigUrl, long startTimeMs)70 public void init(String suitePlan, String dynamicConfigUrl, long startTimeMs) { 71 if (mInitialized) { 72 return; 73 } 74 mInitialized = true; 75 mBuildInfo.addBuildAttribute(SUITE_BUILD, SuiteInfo.BUILD_NUMBER); 76 mBuildInfo.addBuildAttribute(SUITE_NAME, SuiteInfo.NAME); 77 mBuildInfo.addBuildAttribute(SUITE_FULL_NAME, SuiteInfo.FULLNAME); 78 mBuildInfo.addBuildAttribute(SUITE_VERSION, SuiteInfo.VERSION); 79 mBuildInfo.addBuildAttribute(SUITE_PLAN, suitePlan); 80 mBuildInfo.addBuildAttribute(START_TIME_MS, Long.toString(startTimeMs)); 81 mBuildInfo.addBuildAttribute(RESULT_DIR, getDirSuffix(startTimeMs)); 82 String rootDirPath = null; 83 if (mBuildInfo instanceof IFolderBuildInfo) { 84 File rootDir = ((IFolderBuildInfo) mBuildInfo).getRootDir(); 85 if (rootDir != null) { 86 rootDirPath = rootDir.getAbsolutePath(); 87 } 88 } 89 rootDirPath = System.getProperty(String.format("%s_ROOT", SuiteInfo.NAME), rootDirPath); 90 if (rootDirPath == null || rootDirPath.trim().equals("")) { 91 throw new IllegalArgumentException( 92 String.format("Missing install path property %s_ROOT", SuiteInfo.NAME)); 93 } 94 File rootDir = new File(rootDirPath); 95 if (!rootDir.exists()) { 96 throw new IllegalArgumentException( 97 String.format("Root directory doesn't exist %s", rootDir.getAbsolutePath())); 98 } 99 mBuildInfo.addBuildAttribute(ROOT_DIR, rootDir.getAbsolutePath()); 100 if (dynamicConfigUrl != null && !dynamicConfigUrl.isEmpty()) { 101 mBuildInfo.addBuildAttribute(DYNAMIC_CONFIG_OVERRIDE_URL, 102 dynamicConfigUrl.replace("{suite-name}", getSuiteName())); 103 } 104 } 105 getBuildInfo()106 public IBuildInfo getBuildInfo() { 107 return mBuildInfo; 108 } 109 setRetryCommandLineArgs(String commandLineArgs)110 public void setRetryCommandLineArgs(String commandLineArgs) { 111 mBuildInfo.addBuildAttribute(RETRY_COMMAND_LINE_ARGS, commandLineArgs); 112 } 113 getCommandLineArgs()114 public String getCommandLineArgs() { 115 if (mBuildInfo.getBuildAttributes().containsKey(RETRY_COMMAND_LINE_ARGS)) { 116 return mBuildInfo.getBuildAttributes().get(RETRY_COMMAND_LINE_ARGS); 117 } else { 118 // NOTE: this is a temporary workaround set in TestInvocation#invoke in tradefed. 119 // This will be moved to a separate method in a new invocation metadata class. 120 return mBuildInfo.getBuildAttributes().get(COMMAND_LINE_ARGS); 121 } 122 } 123 getSuiteBuild()124 public String getSuiteBuild() { 125 return mBuildInfo.getBuildAttributes().get(SUITE_BUILD); 126 } 127 getSuiteName()128 public String getSuiteName() { 129 return mBuildInfo.getBuildAttributes().get(SUITE_NAME); 130 } 131 getSuiteFullName()132 public String getSuiteFullName() { 133 return mBuildInfo.getBuildAttributes().get(SUITE_FULL_NAME); 134 } 135 getSuiteVersion()136 public String getSuiteVersion() { 137 return mBuildInfo.getBuildAttributes().get(SUITE_VERSION); 138 } 139 getSuitePlan()140 public String getSuitePlan() { 141 return mBuildInfo.getBuildAttributes().get(SUITE_PLAN); 142 } 143 getDynamicConfigUrl()144 public String getDynamicConfigUrl() { 145 return mBuildInfo.getBuildAttributes().get(DYNAMIC_CONFIG_OVERRIDE_URL); 146 } 147 getStartTime()148 public long getStartTime() { 149 return Long.parseLong(mBuildInfo.getBuildAttributes().get(START_TIME_MS)); 150 } 151 addDynamicConfigFile(String moduleName, File configFile)152 public void addDynamicConfigFile(String moduleName, File configFile) { 153 mBuildInfo.addBuildAttribute(CONFIG_PATH_PREFIX + moduleName, configFile.getAbsolutePath()); 154 } 155 setModuleIds(String[] moduleIds)156 public void setModuleIds(String[] moduleIds) { 157 mBuildInfo.addBuildAttribute(MODULE_IDS, String.join(",", moduleIds)); 158 } 159 getDynamicConfigFiles()160 public Map<String, File> getDynamicConfigFiles() { 161 Map<String, File> configMap = new HashMap<>(); 162 for (String key : mBuildInfo.getBuildAttributes().keySet()) { 163 if (key.startsWith(CONFIG_PATH_PREFIX)) { 164 configMap.put(key.substring(CONFIG_PATH_PREFIX.length()), 165 new File(mBuildInfo.getBuildAttributes().get(key))); 166 } 167 } 168 return configMap; 169 } 170 171 /** 172 * @return a {@link File} representing the directory holding the Compatibility installation 173 * @throws FileNotFoundException if the directory does not exist 174 */ getRootDir()175 public File getRootDir() throws FileNotFoundException { 176 File dir = null; 177 if (mBuildInfo instanceof IFolderBuildInfo) { 178 dir = ((IFolderBuildInfo) mBuildInfo).getRootDir(); 179 } 180 if (dir == null || !dir.exists()) { 181 dir = new File(mBuildInfo.getBuildAttributes().get(ROOT_DIR)); 182 if (!dir.exists()) { 183 dir = new File(mBuildInfo.getBuildAttributes().get(ROOT_DIR2)); 184 } 185 } 186 if (!dir.exists()) { 187 throw new FileNotFoundException(String.format( 188 "Compatibility root directory %s does not exist", 189 dir.getAbsolutePath())); 190 } 191 return dir; 192 } 193 194 /** 195 * @return a {@link File} representing the "android-<suite>" folder of the Compatibility 196 * installation 197 * @throws FileNotFoundException if the directory does not exist 198 */ getDir()199 public File getDir() throws FileNotFoundException { 200 File dir = new File(getRootDir(), String.format("android-%s", getSuiteName().toLowerCase())); 201 if (!dir.exists()) { 202 throw new FileNotFoundException(String.format( 203 "Compatibility install folder %s does not exist", 204 dir.getAbsolutePath())); 205 } 206 return dir; 207 } 208 209 /** 210 * @return a {@link File} representing the results directory. 211 * @throws FileNotFoundException if the directory structure is not valid. 212 */ getResultsDir()213 public File getResultsDir() throws FileNotFoundException { 214 return new File(getDir(), "results"); 215 } 216 217 /** 218 * @return a {@link File} representing the result directory of the current invocation. 219 * @throws FileNotFoundException if the directory structure is not valid. 220 */ getResultDir()221 public File getResultDir() throws FileNotFoundException { 222 return new File(getResultsDir(), 223 getDirSuffix(Long.parseLong(mBuildInfo.getBuildAttributes().get(START_TIME_MS)))); 224 } 225 226 /** 227 * @return a {@link File} representing the directory to store result logs. 228 * @throws FileNotFoundException if the directory structure is not valid. 229 */ getLogsDir()230 public File getLogsDir() throws FileNotFoundException { 231 return new File(getDir(), "logs"); 232 } 233 234 /** 235 * @return a {@link File} representing the test modules directory. 236 * @throws FileNotFoundException if the directory structure is not valid. 237 */ getTestsDir()238 public File getTestsDir() throws FileNotFoundException { 239 File testsDir = new File(getDir(), "testcases"); 240 if (!testsDir.exists()) { 241 throw new FileNotFoundException(String.format( 242 "Compatibility tests folder %s does not exist", 243 testsDir.getAbsolutePath())); 244 } 245 return testsDir; 246 } 247 248 /** 249 * @return a {@link String} to use for directory suffixes created from the given time. 250 */ getDirSuffix(long millis)251 public static String getDirSuffix(long millis) { 252 return new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date(millis)); 253 } 254 } 255