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() == Result.UNSUPPORTED) { 93 addEarlyResult(new Outcome(action.getName(), Result.UNSUPPORTED, 94 "Unsupported according to expectations file")); 95 } else { 96 enqueueActionTasks(action); 97 } 98 } 99 100 if (run.cleanAfter) { 101 Set<Task> shutdownTasks = new HashSet<Task>(); 102 shutdownTasks.add(new RmTask(run.rm, run.localTemp)); 103 shutdownTasks.add(run.target.rmTask(run.runnerDir)); 104 for (Task task : shutdownTasks) { 105 task.after(run.taskQueue.getTasks()); 106 } 107 run.taskQueue.enqueueAll(shutdownTasks); 108 } 109 110 run.taskQueue.printTasks(); 111 run.taskQueue.runTasks(); 112 if (run.taskQueue.hasFailedTasks()) { 113 run.taskQueue.printProblemTasks(); 114 return false; 115 } 116 117 if (run.reportPrinter.isReady()) { 118 run.console.info("Printing XML Reports... "); 119 int numFiles = run.reportPrinter.generateReports(outcomes.values()); 120 run.console.info(numFiles + " XML files written."); 121 } 122 123 long t1 = System.currentTimeMillis(); 124 125 Map<String, AnnotatedOutcome> annotatedOutcomes = run.outcomeStore.read(this.outcomes); 126 if (recordResults) { 127 run.outcomeStore.write(outcomes); 128 } 129 130 run.console.summarizeOutcomes(annotatedOutcomes.values()); 131 132 List<String> jarStringList = run.jarSuggestions.getStringList(); 133 if (!jarStringList.isEmpty()) { 134 run.console.warn( 135 "consider adding the following to the classpath:", 136 jarStringList); 137 } 138 139 if (failures > 0 || skipped > 0 || warnings > 0) { 140 run.console.info(String.format( 141 "Outcomes: %s. Passed: %d, Failed: %d, Skipped: %d, Warnings: %d. Took %s.", 142 (successes + failures + warnings + skipped), successes, failures, skipped, warnings, 143 TimeUtilities.msToString(t1 - t0))); 144 } else { 145 run.console.info(String.format("Outcomes: %s. All successful. Took %s.", 146 successes, TimeUtilities.msToString(t1 - t0))); 147 } 148 return failures == 0; 149 } 150 enqueueActionTasks(Action action)151 private void enqueueActionTasks(Action action) { 152 Expectation expectation = run.expectationStore.get(action.getName()); 153 boolean useLargeTimeout = expectation.getTags().contains("large"); 154 File jar = run.hostJar(action); 155 Task build = new BuildActionTask(run, action, this, jar); 156 run.taskQueue.enqueue(build); 157 158 Task prepareUserDir = new PrepareUserDirTask(run.target, action); 159 prepareUserDir.after(installVogarTasks); 160 run.taskQueue.enqueue(prepareUserDir); 161 162 Set<Task> install = run.mode.installActionTasks(action, jar); 163 registerPrerequisites(Collections.singleton(build), install); 164 registerPrerequisites(installVogarTasks, install); 165 registerPrerequisites(Collections.singleton(prepareTargetTask), install); 166 run.taskQueue.enqueueAll(install); 167 168 Task execute = run.mode.executeActionTask(action, useLargeTimeout) 169 .afterSuccess(installVogarTasks) 170 .afterSuccess(build) 171 .afterSuccess(prepareUserDir) 172 .afterSuccess(install); 173 run.taskQueue.enqueue(execute); 174 175 Task retrieveFiles = new RetrieveFilesTask(run, action.getUserDir()).after(execute); 176 run.taskQueue.enqueue(retrieveFiles); 177 178 if (run.cleanAfter) { 179 run.taskQueue.enqueue(new RmTask(run.rm, run.localFile(action)) 180 .after(execute).after(retrieveFiles)); 181 Set<Task> cleanupTasks = run.mode.cleanupTasks(action); 182 for (Task task : cleanupTasks) { 183 task.after(execute).after(retrieveFiles); 184 } 185 run.taskQueue.enqueueAll(cleanupTasks); 186 } 187 } 188 registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter)189 private void registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter) { 190 for (Task task : allAfter) { 191 task.afterSuccess(allBefore); 192 } 193 } 194 classesToActions(Collection<String> classNames)195 private void classesToActions(Collection<String> classNames) { 196 for (String className : classNames) { 197 Action action = new Action(className, className, null, null, null); 198 actions.put(action.getName(), action); 199 } 200 } 201 filesToActions(Collection<File> files)202 private void filesToActions(Collection<File> files) { 203 for (File file : files) { 204 new ActionFinder(run.console, actions, outcomes).findActions(file); 205 } 206 } 207 addEarlyResult(Outcome earlyFailure)208 public synchronized void addEarlyResult(Outcome earlyFailure) { 209 if (earlyFailure.getResult() == Result.UNSUPPORTED) { 210 run.console.verbose("skipped " + earlyFailure.getName()); 211 skipped++; 212 213 } else { 214 for (String line : earlyFailure.getOutputLines()) { 215 run.console.streamOutput(earlyFailure.getName(), line + "\n"); 216 } 217 recordOutcome(earlyFailure); 218 } 219 } 220 recordOutcome(Outcome outcome)221 public synchronized void recordOutcome(Outcome outcome) { 222 outcomes.put(outcome.getName(), outcome); 223 Expectation expectation = run.expectationStore.get(outcome); 224 ResultValue resultValue = outcome.getResultValue(expectation); 225 226 if (resultValue == ResultValue.OK) { 227 successes++; 228 } else if (resultValue == ResultValue.FAIL) { 229 failures++; 230 } else if (resultValue == ResultValue.WARNING) { 231 warnings++; 232 } else { // ResultValue.IGNORE 233 skipped++; 234 } 235 236 Result result = outcome.getResult(); 237 run.console.outcome(outcome.getName()); 238 run.console.printResult(outcome.getName(), result, resultValue, expectation); 239 240 JarSuggestions singleOutcomeJarSuggestions = new JarSuggestions(); 241 singleOutcomeJarSuggestions.addSuggestionsFromOutcome(outcome, run.classFileIndex, 242 run.classpath); 243 List<String> jarStringList = singleOutcomeJarSuggestions.getStringList(); 244 if (!jarStringList.isEmpty()) { 245 run.console.warn( 246 "may have failed because some of these jars are missing from the classpath:", 247 jarStringList); 248 } 249 run.jarSuggestions.addSuggestions(singleOutcomeJarSuggestions); 250 } 251 } 252