1 /* 2 * Copyright (C) 2009 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 vogar; 18 19 import java.io.File; 20 import java.util.Collection; 21 import java.util.Collections; 22 import java.util.HashSet; 23 import java.util.LinkedHashMap; 24 import java.util.List; 25 import java.util.Map; 26 import java.util.Set; 27 import vogar.tasks.BuildActionTask; 28 import vogar.tasks.PrepareTarget; 29 import vogar.tasks.PrepareUserDirTask; 30 import vogar.tasks.RetrieveFilesTask; 31 import vogar.tasks.RmTask; 32 import vogar.tasks.Task; 33 import vogar.util.TimeUtilities; 34 35 /** 36 * Compiles, installs, runs and reports on actions. 37 */ 38 public final class Driver { 39 private final Run run; 40 Driver(Run run)41 public Driver(Run run) { 42 this.run = run; 43 } 44 45 private int successes = 0; 46 private int failures = 0; 47 private int skipped = 0; 48 private int warnings = 0; 49 50 private Task prepareTargetTask; 51 private Set<Task> installVogarTasks; 52 53 private final Map<String, Action> actions = Collections.synchronizedMap( 54 new LinkedHashMap<String, Action>()); 55 private final Map<String, Outcome> outcomes = Collections.synchronizedMap( 56 new LinkedHashMap<String, Outcome>()); 57 public boolean recordResults = true; 58 59 /** 60 * Builds and executes the actions in the given files. 61 */ buildAndRun(Collection<File> files, Collection<String> classes)62 public boolean buildAndRun(Collection<File> files, Collection<String> classes) { 63 if (!actions.isEmpty()) { 64 throw new IllegalStateException("Drivers are not reusable"); 65 } 66 67 run.mkdir.mkdirs(run.localTemp); 68 69 filesToActions(files); 70 classesToActions(classes); 71 72 if (actions.isEmpty()) { 73 run.console.info("Nothing to do."); 74 return false; 75 } 76 77 run.console.info("Actions: " + actions.size()); 78 final long t0 = System.currentTimeMillis(); 79 80 prepareTargetTask = new PrepareTarget(run, run.target); 81 run.taskQueue.enqueue(prepareTargetTask); 82 83 installVogarTasks = run.mode.installTasks(); 84 run.taskQueue.enqueueAll(installVogarTasks); 85 registerPrerequisites(Collections.singleton(prepareTargetTask), installVogarTasks); 86 87 for (Action action : actions.values()) { 88 action.setUserDir(new File(run.runnerDir, action.getName())); 89 Outcome outcome = outcomes.get(action.getName()); 90 if (outcome != null) { 91 addEarlyResult(outcome); 92 } else if (run.expectationStore.get(action.getName()).getResult() 93 == Result.UNSUPPORTED) { 94 addEarlyResult(new Outcome(action.getName(), Result.UNSUPPORTED, 95 "Unsupported according to expectations file")); 96 } else { 97 enqueueActionTasks(action); 98 } 99 } 100 101 if (run.cleanAfter) { 102 Set<Task> shutdownTasks = new HashSet<Task>(); 103 shutdownTasks.add(new RmTask(run.rm, run.localTemp)); 104 shutdownTasks.add(run.target.rmTask(run.runnerDir)); 105 for (Task task : shutdownTasks) { 106 task.after(run.taskQueue.getTasks()); 107 } 108 run.taskQueue.enqueueAll(shutdownTasks); 109 } 110 111 run.taskQueue.printTasks(); 112 run.taskQueue.runTasks(); 113 if (run.taskQueue.hasFailedTasks()) { 114 run.taskQueue.printProblemTasks(); 115 return false; 116 } 117 118 if (run.reportPrinter.isReady()) { 119 run.console.info("Printing XML Reports... "); 120 int numFiles = run.reportPrinter.generateReports(outcomes.values()); 121 run.console.info(numFiles + " XML files written."); 122 } 123 124 long t1 = System.currentTimeMillis(); 125 126 Map<String, AnnotatedOutcome> annotatedOutcomes = run.outcomeStore.read(this.outcomes); 127 if (recordResults) { 128 run.outcomeStore.write(outcomes); 129 } 130 131 run.console.summarizeOutcomes(annotatedOutcomes.values()); 132 133 List<String> jarStringList = run.jarSuggestions.getStringList(); 134 if (!jarStringList.isEmpty()) { 135 run.console.warn( 136 "consider adding the following to the classpath:", 137 jarStringList); 138 } 139 140 if (failures > 0 || skipped > 0 || warnings > 0) { 141 run.console.info(String.format( 142 "Outcomes: %s. Passed: %d, Failed: %d, Skipped: %d, Warnings: %d. Took %s.", 143 (successes + failures + warnings + skipped), successes, failures, skipped, warnings, 144 TimeUtilities.msToString(t1 - t0))); 145 } else { 146 run.console.info(String.format("Outcomes: %s. All successful. Took %s.", 147 successes, TimeUtilities.msToString(t1 - t0))); 148 } 149 return failures == 0; 150 } 151 enqueueActionTasks(Action action)152 private void enqueueActionTasks(Action action) { 153 Expectation expectation = run.expectationStore.get(action.getName()); 154 boolean useLargeTimeout = expectation.getTags().contains("large"); 155 File jar = run.hostJar(action); 156 Task build = new BuildActionTask(run, action, this, jar); 157 run.taskQueue.enqueue(build); 158 159 Task prepareUserDir = new PrepareUserDirTask(run.target, action); 160 prepareUserDir.after(installVogarTasks); 161 run.taskQueue.enqueue(prepareUserDir); 162 163 Set<Task> install = run.mode.installActionTasks(action, jar); 164 registerPrerequisites(Collections.singleton(build), install); 165 registerPrerequisites(installVogarTasks, install); 166 registerPrerequisites(Collections.singleton(prepareTargetTask), install); 167 run.taskQueue.enqueueAll(install); 168 169 Task execute = run.mode.executeActionTask(action, useLargeTimeout) 170 .afterSuccess(installVogarTasks) 171 .afterSuccess(build) 172 .afterSuccess(prepareUserDir) 173 .afterSuccess(install); 174 run.taskQueue.enqueue(execute); 175 176 Task retrieveFiles = new RetrieveFilesTask(run, action.getUserDir()).after(execute); 177 run.taskQueue.enqueue(retrieveFiles); 178 179 if (run.cleanAfter) { 180 run.taskQueue.enqueue(new RmTask(run.rm, run.localFile(action)) 181 .after(execute).after(retrieveFiles)); 182 Set<Task> cleanupTasks = run.mode.cleanupTasks(action); 183 for (Task task : cleanupTasks) { 184 task.after(execute).after(retrieveFiles); 185 } 186 run.taskQueue.enqueueAll(cleanupTasks); 187 } 188 } 189 registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter)190 private void registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter) { 191 for (Task task : allAfter) { 192 task.afterSuccess(allBefore); 193 } 194 } 195 classesToActions(Collection<String> classNames)196 private void classesToActions(Collection<String> classNames) { 197 for (String className : classNames) { 198 Action action = new Action(className, className, null, null, null); 199 actions.put(action.getName(), action); 200 } 201 } 202 filesToActions(Collection<File> files)203 private void filesToActions(Collection<File> files) { 204 for (File file : files) { 205 new ActionFinder(run.console, actions, outcomes).findActions(file); 206 } 207 } 208 addEarlyResult(Outcome earlyFailure)209 public synchronized void addEarlyResult(Outcome earlyFailure) { 210 if (earlyFailure.getResult() == Result.UNSUPPORTED) { 211 run.console.verbose("skipped " + earlyFailure.getName()); 212 skipped++; 213 214 } else { 215 for (String line : earlyFailure.getOutputLines()) { 216 run.console.streamOutput(earlyFailure.getName(), line + "\n"); 217 } 218 recordOutcome(earlyFailure); 219 } 220 } 221 recordOutcome(Outcome outcome)222 public synchronized void recordOutcome(Outcome outcome) { 223 outcomes.put(outcome.getName(), outcome); 224 Expectation expectation = run.expectationStore.get(outcome); 225 ResultValue resultValue = outcome.getResultValue(expectation); 226 227 if (resultValue == ResultValue.OK) { 228 successes++; 229 } else if (resultValue == ResultValue.FAIL) { 230 failures++; 231 } else if (resultValue == ResultValue.WARNING) { 232 warnings++; 233 } else { // ResultValue.IGNORE 234 skipped++; 235 } 236 237 Result result = outcome.getResult(); 238 run.console.outcome(outcome.getName()); 239 run.console.printResult(outcome.getName(), result, resultValue, expectation); 240 241 JarSuggestions singleOutcomeJarSuggestions = new JarSuggestions(); 242 singleOutcomeJarSuggestions.addSuggestionsFromOutcome(outcome, run.classFileIndex, 243 run.classpath); 244 List<String> jarStringList = singleOutcomeJarSuggestions.getStringList(); 245 if (!jarStringList.isEmpty()) { 246 run.console.warn( 247 "may have failed because some of these jars are missing from the classpath:", 248 jarStringList); 249 } 250 run.jarSuggestions.addSuggestions(singleOutcomeJarSuggestions); 251 } 252 } 253