| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package vogar; |
| |
| import java.io.File; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import vogar.tasks.BuildActionTask; |
| import vogar.tasks.PrepareTarget; |
| import vogar.tasks.PrepareUserDirTask; |
| import vogar.tasks.RetrieveFilesTask; |
| import vogar.tasks.RmTask; |
| import vogar.tasks.Task; |
| import vogar.util.TimeUtilities; |
| |
| /** |
| * Compiles, installs, runs and reports on actions. |
| */ |
| public final class Driver { |
| private final Run run; |
| |
| public Driver(Run run) { |
| this.run = run; |
| } |
| |
| private int successes = 0; |
| private int failures = 0; |
| private int skipped = 0; |
| private int warnings = 0; |
| |
| private Task prepareTargetTask; |
| private Set<Task> installVogarTasks; |
| |
| private final Map<String, Action> actions = Collections.synchronizedMap( |
| new LinkedHashMap<String, Action>()); |
| private final Map<String, Outcome> outcomes = Collections.synchronizedMap( |
| new LinkedHashMap<String, Outcome>()); |
| public boolean recordResults = true; |
| |
| /** |
| * Builds and executes the actions in the given files. |
| */ |
| public boolean buildAndRun(Collection<File> files, Collection<String> classes) { |
| if (!actions.isEmpty()) { |
| throw new IllegalStateException("Drivers are not reusable"); |
| } |
| |
| run.mkdir.mkdirs(run.localTemp); |
| |
| filesToActions(files); |
| classesToActions(classes); |
| |
| if (actions.isEmpty()) { |
| run.console.info("Nothing to do."); |
| return false; |
| } |
| |
| run.console.info("Actions: " + actions.size()); |
| final long t0 = System.currentTimeMillis(); |
| |
| prepareTargetTask = new PrepareTarget(run, run.target); |
| run.taskQueue.enqueue(prepareTargetTask); |
| |
| installVogarTasks = run.mode.installTasks(); |
| run.taskQueue.enqueueAll(installVogarTasks); |
| registerPrerequisites(Collections.singleton(prepareTargetTask), installVogarTasks); |
| |
| for (Action action : actions.values()) { |
| action.setUserDir(new File(run.runnerDir, action.getName())); |
| Outcome outcome = outcomes.get(action.getName()); |
| if (outcome != null) { |
| addEarlyResult(outcome); |
| } else if (run.expectationStore.get(action.getName()).getResult() |
| == Result.UNSUPPORTED) { |
| addEarlyResult(new Outcome(action.getName(), Result.UNSUPPORTED, |
| "Unsupported according to expectations file")); |
| } else { |
| enqueueActionTasks(action); |
| } |
| } |
| |
| if (run.cleanAfter) { |
| Set<Task> shutdownTasks = new HashSet<Task>(); |
| shutdownTasks.add(new RmTask(run.rm, run.localTemp)); |
| shutdownTasks.add(run.target.rmTask(run.runnerDir)); |
| for (Task task : shutdownTasks) { |
| task.after(run.taskQueue.getTasks()); |
| } |
| run.taskQueue.enqueueAll(shutdownTasks); |
| } |
| |
| run.taskQueue.printTasks(); |
| run.taskQueue.runTasks(); |
| if (run.taskQueue.hasFailedTasks()) { |
| run.taskQueue.printProblemTasks(); |
| return false; |
| } |
| |
| if (run.reportPrinter.isReady()) { |
| run.console.info("Printing XML Reports... "); |
| int numFiles = run.reportPrinter.generateReports(outcomes.values()); |
| run.console.info(numFiles + " XML files written."); |
| } |
| |
| long t1 = System.currentTimeMillis(); |
| |
| Map<String, AnnotatedOutcome> annotatedOutcomes = run.outcomeStore.read(this.outcomes); |
| if (recordResults) { |
| run.outcomeStore.write(outcomes); |
| } |
| |
| run.console.summarizeOutcomes(annotatedOutcomes.values()); |
| |
| List<String> jarStringList = run.jarSuggestions.getStringList(); |
| if (!jarStringList.isEmpty()) { |
| run.console.warn( |
| "consider adding the following to the classpath:", |
| jarStringList); |
| } |
| |
| if (failures > 0 || skipped > 0 || warnings > 0) { |
| run.console.info(String.format( |
| "Outcomes: %s. Passed: %d, Failed: %d, Skipped: %d, Warnings: %d. Took %s.", |
| (successes + failures + warnings + skipped), successes, failures, skipped, warnings, |
| TimeUtilities.msToString(t1 - t0))); |
| } else { |
| run.console.info(String.format("Outcomes: %s. All successful. Took %s.", |
| successes, TimeUtilities.msToString(t1 - t0))); |
| } |
| return failures == 0; |
| } |
| |
| private void enqueueActionTasks(Action action) { |
| Expectation expectation = run.expectationStore.get(action.getName()); |
| boolean useLargeTimeout = expectation.getTags().contains("large"); |
| File jar = run.hostJar(action); |
| Task build = new BuildActionTask(run, action, this, jar); |
| run.taskQueue.enqueue(build); |
| |
| Task prepareUserDir = new PrepareUserDirTask(run.target, action); |
| prepareUserDir.after(installVogarTasks); |
| run.taskQueue.enqueue(prepareUserDir); |
| |
| Set<Task> install = run.mode.installActionTasks(action, jar); |
| registerPrerequisites(Collections.singleton(build), install); |
| registerPrerequisites(installVogarTasks, install); |
| registerPrerequisites(Collections.singleton(prepareTargetTask), install); |
| run.taskQueue.enqueueAll(install); |
| |
| Task execute = run.mode.executeActionTask(action, useLargeTimeout) |
| .afterSuccess(installVogarTasks) |
| .afterSuccess(build) |
| .afterSuccess(prepareUserDir) |
| .afterSuccess(install); |
| run.taskQueue.enqueue(execute); |
| |
| Task retrieveFiles = new RetrieveFilesTask(run, action.getUserDir()).after(execute); |
| run.taskQueue.enqueue(retrieveFiles); |
| |
| if (run.cleanAfter) { |
| run.taskQueue.enqueue(new RmTask(run.rm, run.localFile(action)) |
| .after(execute).after(retrieveFiles)); |
| Set<Task> cleanupTasks = run.mode.cleanupTasks(action); |
| for (Task task : cleanupTasks) { |
| task.after(execute).after(retrieveFiles); |
| } |
| run.taskQueue.enqueueAll(cleanupTasks); |
| } |
| } |
| |
| private void registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter) { |
| for (Task task : allAfter) { |
| task.afterSuccess(allBefore); |
| } |
| } |
| |
| private void classesToActions(Collection<String> classNames) { |
| for (String className : classNames) { |
| Action action = new Action(className, className, null, null, null); |
| actions.put(action.getName(), action); |
| } |
| } |
| |
| private void filesToActions(Collection<File> files) { |
| for (File file : files) { |
| new ActionFinder(run.console, actions, outcomes).findActions(file); |
| } |
| } |
| |
| public synchronized void addEarlyResult(Outcome earlyFailure) { |
| if (earlyFailure.getResult() == Result.UNSUPPORTED) { |
| run.console.verbose("skipped " + earlyFailure.getName()); |
| skipped++; |
| |
| } else { |
| for (String line : earlyFailure.getOutputLines()) { |
| run.console.streamOutput(earlyFailure.getName(), line + "\n"); |
| } |
| recordOutcome(earlyFailure); |
| } |
| } |
| |
| public synchronized void recordOutcome(Outcome outcome) { |
| outcomes.put(outcome.getName(), outcome); |
| Expectation expectation = run.expectationStore.get(outcome); |
| ResultValue resultValue = outcome.getResultValue(expectation); |
| |
| if (resultValue == ResultValue.OK) { |
| successes++; |
| } else if (resultValue == ResultValue.FAIL) { |
| failures++; |
| } else if (resultValue == ResultValue.WARNING) { |
| warnings++; |
| } else { // ResultValue.IGNORE |
| skipped++; |
| } |
| |
| Result result = outcome.getResult(); |
| run.console.outcome(outcome.getName()); |
| run.console.printResult(outcome.getName(), result, resultValue, expectation); |
| |
| JarSuggestions singleOutcomeJarSuggestions = new JarSuggestions(); |
| singleOutcomeJarSuggestions.addSuggestionsFromOutcome(outcome, run.classFileIndex, |
| run.classpath); |
| List<String> jarStringList = singleOutcomeJarSuggestions.getStringList(); |
| if (!jarStringList.isEmpty()) { |
| run.console.warn( |
| "may have failed because some of these jars are missing from the classpath:", |
| jarStringList); |
| } |
| run.jarSuggestions.addSuggestions(singleOutcomeJarSuggestions); |
| } |
| } |