public void run()

in src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java [366:586]


    public void run() {
        res = new IgnoredTestResult();
        res.addListener(wrapListener(this));
        for (JUnitTaskMirror.JUnitResultFormatterMirror f : formatters) {
            res.addListener(wrapListener((TestListener) f));
        }

        final ByteArrayOutputStream errStrm = new ByteArrayOutputStream();
        final ByteArrayOutputStream outStrm = new ByteArrayOutputStream();

        setupIOStreams(outStrm, errStrm);

        Test suite = null;
        Throwable exception = null;
        boolean startTestSuiteSuccess = false;

        try {

            try {
                Class<?> testClass;
                if (loader == null) {
                    testClass = Class.forName(junitTest.getName(), false,
                                              getClass().getClassLoader());
                } else {
                    testClass = Class.forName(junitTest.getName(), false,
                                              loader);
                }

                final boolean testMethodsSpecified = (methods != null);

                // check for a static suite method first, even when using
                // JUnit 4
                Method suiteMethod = null;
                if (!testMethodsSpecified) {
                    try {
                        // check if there is a suite method
                        suiteMethod = testClass.getMethod("suite");
                    } catch (final NoSuchMethodException e) {
                        // no appropriate suite method found. We don't report any
                        // error here since it might be perfectly normal.
                    }
                }

                if (suiteMethod != null) {
                    // if there is a suite method available, then try
                    // to extract the suite from it. If there is an error
                    // here it will be caught below and reported.
                    suite = (Test) suiteMethod.invoke(null);

                } else {
                    Class<?> junit4TestAdapterClass = null;
                    Class<?> junit4TestAdapterCacheClass = null;
                    boolean useSingleMethodAdapter = false;

                    if (junit.framework.TestCase.class.isAssignableFrom(testClass)) {
                        // Do not use JUnit 4 API for running JUnit 3.x
                        // tests - it is not able to run individual test
                        // methods.
                        //
                        // Technical details:
                        // org.junit.runner.Request.method(Class, String).getRunner()
                        // would return a runner which always executes all
                        // test methods. The reason is that the Runner would be
                        // an instance of class
                        // org.junit.internal.runners.OldTestClassRunner
                        // that does not implement interface Filterable - so it
                        // is unable to filter out test methods not matching
                        // the requested name.
                    } else {
                    // Check for JDK 5 first. Will *not* help on JDK 1.4
                    // if only junit-4.0.jar in CP because in that case
                    // linkage of whole task will already have failed! But
                    // will help if CP has junit-3.8.2.jar:junit-4.0.jar.

                    // In that case first C.fN will fail with CNFE and we
                    // will avoid UnsupportedClassVersionError.

                        try {
                            Class.forName("java.lang.annotation.Annotation");
                            junit4TestAdapterCacheClass = Class.forName(
                                "org.apache.tools.ant.taskdefs.optional.junit.CustomJUnit4TestAdapterCache");
                            if (loader == null) {
                                junit4TestAdapterClass = Class.forName(JUNIT_4_TEST_ADAPTER);
                                if (testMethodsSpecified) {
                                    /*
                                     * We cannot try to load the JUnit4TestAdapter
                                     * before trying to load JUnit4TestMethodAdapter
                                     * because it might fail with
                                     * NoClassDefFoundException, instead of plain
                                     * ClassNotFoundException.
                                     */
                                    junit4TestAdapterClass = Class.forName(
                                        "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter");
                                    useSingleMethodAdapter = true;
                                }
                            } else {
                                junit4TestAdapterClass =
                                    Class.forName(JUNIT_4_TEST_ADAPTER,
                                                  true, loader);
                                if (testMethodsSpecified) {
                                    junit4TestAdapterClass = Class.forName(
                                            "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter",
                                            true, loader);
                                    useSingleMethodAdapter = true;
                                }
                            }
                        } catch (final ClassNotFoundException e) {
                            // OK, fall back to JUnit 3.
                        }
                    }
                    junit4 = junit4TestAdapterClass != null;

                    if (junitTest.isSkipNonTests()
                        && !containsTests(testClass, junit4)) {
                        return;
                    }

                    if (junit4) {
                        // Let's use it!
                        Class<?>[] formalParams;
                        Object[] actualParams;
                        if (useSingleMethodAdapter) {
                            formalParams = new Class[] {Class.class, String[].class};
                            actualParams = new Object[] {testClass, methods};
                        } else {
                            formalParams = new Class[] {Class.class, Class.forName(
                                    "junit.framework.JUnit4TestAdapterCache")};
                            actualParams = new Object[] {testClass, junit4TestAdapterCacheClass
                                    .getMethod("getInstance").invoke(null)};
                        }
                        suite = junit4TestAdapterClass.asSubclass(Test.class)
                                .getConstructor(formalParams).newInstance(actualParams);
                    } else {
                        // Use JUnit 3.

                        // try to extract a test suite automatically this
                        // will generate warnings if the class is no
                        // suitable Test
                        if (!testMethodsSpecified) {
                            suite = new TestSuite(testClass);
                        } else if (methods.length == 1) {
                            suite = TestSuite.createTest(testClass, methods[0]);
                        } else {
                            final TestSuite testSuite = new TestSuite(testClass.getName());
                            for (String method : methods) {
                                testSuite.addTest(TestSuite.createTest(testClass, method));
                            }
                            suite = testSuite;
                        }
                    }
                }
            } catch (final Throwable e) {
                retCode = ERRORS;
                exception = e;
            }

            final long start = System.currentTimeMillis();

            fireStartTestSuite();
            startTestSuiteSuccess = true;
            if (exception != null) { // had an exception constructing suite
                for (JUnitTaskMirror.JUnitResultFormatterMirror f : formatters) {
                    ((TestListener) f).addError(null, exception);
                }
                junitTest.setCounts(1, 0, 1, 0);
                junitTest.setRunTime(0);
            } else {
                try {
                    logTestListenerEvent("tests to run: " + suite.countTestCases());
                    suite.run(res);
                } finally {
                    if (junit4 || suite.getClass().getName().equals(JUNIT_4_TEST_ADAPTER)) {
                        final int[] cnts = findJUnit4FailureErrorCount(res);
                        junitTest.setCounts(res.runCount() + res.ignoredCount(), cnts[0], cnts[1],
                                res.ignoredCount() + res.skippedCount());
                    } else {
                        junitTest.setCounts(res.runCount() + res.ignoredCount(), res.failureCount(),
                                res.errorCount(), res.ignoredCount() + res.skippedCount());
                    }
                    junitTest.setRunTime(System.currentTimeMillis() - start);
                }
            }
        } finally {
            if (perm != null) {
                perm.restoreSecurityManager();
            }
            if (savedOut != null) {
                System.setOut(savedOut);
            }
            if (savedErr != null) {
                System.setErr(savedErr);
            }

            systemError.close();
            systemError = null;
            systemOut.close();
            systemOut = null;
            if (startTestSuiteSuccess) {
                String out, err;
                try {
                    out = new String(outStrm.toByteArray());
                } catch (final OutOfMemoryError ex) {
                    out = "out of memory on output stream";
                }
                try {
                    err = new String(errStrm.toByteArray());
                } catch (final OutOfMemoryError ex) {
                    err = "out of memory on error stream";
                }
                sendOutAndErr(out, err);
            }
        }
        fireEndTestSuite();

        // junitTest has the correct counts for JUnit4, while res doesn't
        if (retCode != SUCCESS || junitTest.errorCount() != 0) {
            retCode = ERRORS;
        } else if (junitTest.failureCount() != 0) {
            retCode = FAILURES;
        }
    }