Java程序  |  252行  |  9.14 KB

/*
 * 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);
    }
}