Home | History | Annotate | Download | only in vogar
      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 
     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      */
     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 
    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 
    189     private void registerPrerequisites(Set<Task> allBefore, Set<Task> allAfter) {
    190         for (Task task : allAfter) {
    191             task.afterSuccess(allBefore);
    192         }
    193     }
    194 
    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 
    202     private void filesToActions(Collection<File> files) {
    203         for (File file : files) {
    204             new ActionFinder(run.console, actions, outcomes).findActions(file);
    205         }
    206     }
    207 
    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 
    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