Search in sources :

Example 1 with FilterExpressionParser

use of com.carrotsearch.randomizedtesting.FilterExpressionParser in project randomizedtesting by randomizedtesting.

the class JUnit4 method execute.

@Override
public void execute() throws BuildException {
    validateJUnit4();
    validateArguments();
    // Initialize random if not already provided.
    if (random == null) {
        this.random = MoreObjects.firstNonNull(Strings.emptyToNull(getProject().getProperty(SYSPROP_RANDOM_SEED())), SeedUtils.formatSeed(new Random().nextLong()));
    }
    masterSeed();
    // Say hello and continue.
    log("<JUnit4> says " + RandomPicks.randomFrom(new Random(masterSeed()), WELCOME_MESSAGES) + " Master seed: " + getSeed(), Project.MSG_INFO);
    // Pass the random seed property.
    createJvmarg().setValue("-D" + SYSPROP_PREFIX() + "=" + CURRENT_PREFIX());
    createJvmarg().setValue("-D" + SYSPROP_RANDOM_SEED() + "=" + random);
    // Resolve paths first.
    this.classpath = resolveFiles(classpath);
    this.bootclasspath = resolveFiles(bootclasspath);
    getCommandline().createClasspath(getProject()).add(classpath);
    getCommandline().createBootclasspath(getProject()).add(bootclasspath);
    // Setup a class loader over test classes. This will be used for loading annotations
    // and referenced classes. This is kind of ugly, but mirroring annotation content will
    // be even worse and Description carries these.
    // TODO: [GH-211] we should NOT be using any actual classes, annotations, etc. 
    // from client code. Everything should be a mirror.
    testsClassLoader = new AntClassLoader(this.getClass().getClassLoader(), getProject(), getCommandline().getClasspath(), true);
    // Pass method filter if any.
    String testMethodFilter = Strings.emptyToNull(getProject().getProperty(SYSPROP_TESTMETHOD()));
    if (testMethodFilter != null) {
        Environment.Variable v = new Environment.Variable();
        v.setKey(SYSPROP_TESTMETHOD());
        v.setValue(testMethodFilter);
        getCommandline().addSysproperty(v);
    }
    // Process test classes and resources.
    long start = System.currentTimeMillis();
    final TestsCollection testCollection = processTestResources();
    final EventBus aggregatedBus = new EventBus("aggregated");
    final TestsSummaryEventListener summaryListener = new TestsSummaryEventListener();
    aggregatedBus.register(summaryListener);
    for (Object o : listeners) {
        if (o instanceof ProjectComponent) {
            ((ProjectComponent) o).setProject(getProject());
        }
        if (o instanceof AggregatedEventListener) {
            ((AggregatedEventListener) o).setOuter(this);
        }
        aggregatedBus.register(o);
    }
    if (testCollection.testClasses.isEmpty()) {
        aggregatedBus.post(new AggregatedQuitEvent());
    } else {
        start = System.currentTimeMillis();
        // reports) will have a problem with duplicate suite names, for example.
        if (uniqueSuiteNames) {
            testCollection.onlyUniqueSuiteNames();
        }
        final int jvmCount = determineForkedJvmCount(testCollection);
        final List<ForkedJvmInfo> slaveInfos = new ArrayList<>();
        for (int jvmid = 0; jvmid < jvmCount; jvmid++) {
            final ForkedJvmInfo slaveInfo = new ForkedJvmInfo(jvmid, jvmCount);
            slaveInfos.add(slaveInfo);
        }
        if (jvmCount > 1 && uniqueSuiteNames && testCollection.hasReplicatedSuites()) {
            throw new BuildException(String.format(Locale.ROOT, "There are test suites that request JVM replication and the number of forked JVMs %d is larger than 1. Run on a single JVM.", jvmCount));
        }
        // Prepare a pool of suites dynamically dispatched to slaves as they become idle.
        final Deque<String> stealingQueue = new ArrayDeque<String>(loadBalanceSuites(slaveInfos, testCollection, balancers));
        aggregatedBus.register(new Object() {

            @Subscribe
            public void onSlaveIdle(SlaveIdle slave) {
                if (stealingQueue.isEmpty()) {
                    slave.finished();
                } else {
                    String suiteName = stealingQueue.pop();
                    slave.newSuite(suiteName);
                }
            }
        });
        // Check for filtering expressions.
        Vector<Variable> vv = getCommandline().getSystemProperties().getVariablesVector();
        for (Variable v : vv) {
            if (SysGlobals.SYSPROP_TESTFILTER().equals(v.getKey())) {
                try {
                    Node root = new FilterExpressionParser().parse(v.getValue());
                    log("Parsed test filtering expression: " + root.toExpression(), Project.MSG_INFO);
                } catch (Exception e) {
                    log("Could not parse filtering expression: " + v.getValue(), e, Project.MSG_WARN);
                }
            }
        }
        // Create callables for the executor.
        final List<Callable<Void>> slaves = new ArrayList<>();
        for (int slave = 0; slave < jvmCount; slave++) {
            final ForkedJvmInfo slaveInfo = slaveInfos.get(slave);
            slaves.add(new Callable<Void>() {

                @Override
                public Void call() throws Exception {
                    executeSlave(slaveInfo, aggregatedBus);
                    return null;
                }
            });
        }
        ExecutorService executor = Executors.newCachedThreadPool();
        aggregatedBus.post(new AggregatedStartEvent(slaves.size(), // TODO: this doesn't account for replicated suites.
        testCollection.testClasses.size()));
        try {
            List<Future<Void>> all = executor.invokeAll(slaves);
            executor.shutdown();
            for (int i = 0; i < slaves.size(); i++) {
                Future<Void> f = all.get(i);
                try {
                    f.get();
                } catch (ExecutionException e) {
                    slaveInfos.get(i).executionError = e.getCause();
                }
            }
        } catch (InterruptedException e) {
            log("Master interrupted? Weird.", Project.MSG_ERR);
        }
        aggregatedBus.post(new AggregatedQuitEvent());
        for (ForkedJvmInfo si : slaveInfos) {
            if (si.start > 0 && si.end > 0) {
                log(String.format(Locale.ROOT, "JVM J%d: %8.2f .. %8.2f = %8.2fs", si.id, (si.start - start) / 1000.0f, (si.end - start) / 1000.0f, (si.getExecutionTime() / 1000.0f)), Project.MSG_INFO);
            }
        }
        log("Execution time total: " + Duration.toHumanDuration((System.currentTimeMillis() - start)));
        ForkedJvmInfo slaveInError = null;
        for (ForkedJvmInfo i : slaveInfos) {
            if (i.executionError != null) {
                log("ERROR: JVM J" + i.id + " ended with an exception, command line: " + i.getCommandLine());
                log("ERROR: JVM J" + i.id + " ended with an exception: " + Throwables.getStackTraceAsString(i.executionError), Project.MSG_ERR);
                if (slaveInError == null) {
                    slaveInError = i;
                }
            }
        }
        if (slaveInError != null) {
            throw new BuildException("At least one slave process threw an exception, first: " + slaveInError.executionError.getMessage(), slaveInError.executionError);
        }
    }
    final TestsSummary testsSummary = summaryListener.getResult();
    if (printSummary) {
        log("Tests summary: " + testsSummary, Project.MSG_INFO);
    }
    if (!testsSummary.isSuccessful()) {
        if (!Strings.isNullOrEmpty(failureProperty)) {
            getProject().setNewProperty(failureProperty, "true");
        }
        if (haltOnFailure) {
            throw new BuildException(String.format(Locale.ROOT, "There were test failures: %s [seed: %s]", testsSummary, getSeed()));
        }
    }
    if (!leaveTemporary) {
        for (Path f : temporaryFiles) {
            try {
                if (f != null) {
                    try {
                        Files.delete(f);
                    } catch (DirectoryNotEmptyException e) {
                        throw new DirectoryNotEmptyException("Remaining files: " + listFiles(f));
                    }
                }
            } catch (IOException e) {
                log("Could not remove temporary path: " + f.toAbsolutePath() + " (" + e + ")", e, Project.MSG_WARN);
            }
        }
    }
    if (statsPropertyPrefix != null) {
        Project p = getProject();
        p.setNewProperty(statsPropertyPrefix + ".tests", Integer.toString(testsSummary.tests));
        p.setNewProperty(statsPropertyPrefix + ".errors", Integer.toString(testsSummary.errors));
        p.setNewProperty(statsPropertyPrefix + ".failures", Integer.toString(testsSummary.failures));
        p.setNewProperty(statsPropertyPrefix + ".ignores", Integer.toString(testsSummary.ignores));
        p.setNewProperty(statsPropertyPrefix + ".suites", Integer.toString(testsSummary.suites));
        p.setNewProperty(statsPropertyPrefix + ".assumptions", Integer.toString(testsSummary.assumptions));
        p.setNewProperty(statsPropertyPrefix + ".suiteErrors", Integer.toString(testsSummary.suiteErrors));
        p.setNewProperty(statsPropertyPrefix + ".nonIgnored", Integer.toString(testsSummary.getNonIgnoredTestsCount()));
        p.setNewProperty(statsPropertyPrefix + ".successful", Boolean.toString(testsSummary.isSuccessful()));
    }
    int executedTests = testsSummary.getNonIgnoredTestsCount();
    if (executedTests == 0) {
        String message = "There were no executed tests: " + testsSummary;
        switch(ifNoTests) {
            case FAIL:
                throw new BuildException(message);
            case WARN:
                log(message, Project.MSG_WARN);
                break;
            case IGNORE:
                break;
            default:
                throw new RuntimeException("Unreachable case clause: " + ifNoTests);
        }
    }
}
Also used : ProjectComponent(org.apache.tools.ant.ProjectComponent) Variable(org.apache.tools.ant.types.Environment.Variable) FilterExpressionParser(com.carrotsearch.randomizedtesting.FilterExpressionParser) Node(com.carrotsearch.randomizedtesting.FilterExpressionParser.Node) ArrayList(java.util.ArrayList) AntClassLoader(org.apache.tools.ant.AntClassLoader) DirectoryNotEmptyException(java.nio.file.DirectoryNotEmptyException) EventBus(com.google.common.eventbus.EventBus) Subscribe(com.google.common.eventbus.Subscribe) Variable(org.apache.tools.ant.types.Environment.Variable) Callable(java.util.concurrent.Callable) Random(java.util.Random) AggregatedStartEvent(com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent) ExecutionException(java.util.concurrent.ExecutionException) Path(java.nio.file.Path) AggregatedEventListener(com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener) IOException(java.io.IOException) SuiteHint(com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint) ArrayDeque(java.util.ArrayDeque) DirectoryNotEmptyException(java.nio.file.DirectoryNotEmptyException) IOException(java.io.IOException) BuildException(org.apache.tools.ant.BuildException) ExecutionException(java.util.concurrent.ExecutionException) Project(org.apache.tools.ant.Project) AggregatedQuitEvent(com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent) ExecutorService(java.util.concurrent.ExecutorService) Environment(org.apache.tools.ant.types.Environment) Future(java.util.concurrent.Future) BuildException(org.apache.tools.ant.BuildException)

Aggregations

SuiteHint (com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint)1 AggregatedQuitEvent (com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent)1 AggregatedStartEvent (com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent)1 AggregatedEventListener (com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener)1 FilterExpressionParser (com.carrotsearch.randomizedtesting.FilterExpressionParser)1 Node (com.carrotsearch.randomizedtesting.FilterExpressionParser.Node)1 EventBus (com.google.common.eventbus.EventBus)1 Subscribe (com.google.common.eventbus.Subscribe)1 IOException (java.io.IOException)1 DirectoryNotEmptyException (java.nio.file.DirectoryNotEmptyException)1 Path (java.nio.file.Path)1 ArrayDeque (java.util.ArrayDeque)1 ArrayList (java.util.ArrayList)1 Random (java.util.Random)1 Callable (java.util.concurrent.Callable)1 ExecutionException (java.util.concurrent.ExecutionException)1 ExecutorService (java.util.concurrent.ExecutorService)1 Future (java.util.concurrent.Future)1 AntClassLoader (org.apache.tools.ant.AntClassLoader)1 BuildException (org.apache.tools.ant.BuildException)1