[SUREFIRE-580] configuration parameter 'skipAfterFailureCount'
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/779e3811 Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/779e3811 Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/779e3811 Branch: refs/heads/master Commit: 779e381102a8f882e58c95ad3e50eadca170cba7 Parents: 1b7fe2d Author: Tibor17 <tibo...@lycos.com> Authored: Sat Sep 5 01:15:07 2015 +0200 Committer: Tibor17 <tibo...@lycos.com> Committed: Sun Sep 6 22:58:04 2015 +0200 ---------------------------------------------------------------------- .../surefire/booterclient/ForkStarter.java | 12 ++- surefire-api/pom.xml | 6 ++ .../util/internal/ConcurrencyUtils.java | 64 ++++++++++++ .../java/org/apache/maven/JUnit4SuiteTest.java | 78 ++++++++++++++ .../util/internal/ConcurrencyUtilsTest.java | 104 +++++++++++++++++++ .../maven/surefire/common/junit4/Notifier.java | 35 ++++--- .../maven/surefire/common/junit4/Stoppable.java | 35 +++++++ .../surefire/junit4/JUnit4FailFastListener.java | 13 +-- .../maven/surefire/junit4/JUnit4Provider.java | 11 +- .../junitcore/JUnit47FailFastListener.java | 5 +- .../maven/surefire/junitcore/JUnitCore.java | 11 -- .../surefire/junitcore/JUnitCoreProvider.java | 9 +- .../surefire/junitcore/JUnitCoreWrapper.java | 15 ++- .../maven/surefire/junitcore/Stoppable.java | 32 ------ .../surefire/testng/utils/FailFastListener.java | 3 +- .../maven/surefire/testng/utils/Stoppable.java | 4 +- .../testng/TestNGDirectoryTestSuite.java | 15 +-- .../maven/surefire/testng/TestNGExecutor.java | 43 +++++--- .../maven/surefire/testng/TestNGProvider.java | 10 +- .../surefire/testng/TestNGXmlTestSuite.java | 8 +- 20 files changed, 397 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java index 632834f..396e99f 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java @@ -67,7 +67,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.apache.maven.shared.utils.cli.CommandLineUtils.executeCommandLine; @@ -79,6 +79,7 @@ import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDae import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder; import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider. TestLessInputStream.TestLessInputStreamBuilder; +import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; import static org.apache.maven.surefire.booter.Classpath.join; import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile; import static org.apache.maven.surefire.suite.RunResult.timeout; @@ -248,7 +249,7 @@ public class ForkStarter testStreams.add( new TestProvidingInputStream( tests ) ); } - final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean(); + final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger(); Collection<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount ); for ( final TestProvidingInputStream testProvidingInputStream : testStreams ) { @@ -267,7 +268,7 @@ public class ForkStarter @Override protected void stopOnNextTest() { - if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) ) + if ( countDownToZero( notifyStreamsToSkipTestsJustNow ) ) { notifyStreamsToSkipTests( testStreams ); } @@ -306,7 +307,8 @@ public class ForkStarter executorService.setThreadFactory( threadFactory ); try { - final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean(); + int failFastCount = providerConfiguration.getSkipAfterFailureCount(); + final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger( failFastCount ); final TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder(); for ( final Object testSet : getSuitesIterator() ) { @@ -324,7 +326,7 @@ public class ForkStarter @Override protected void stopOnNextTest() { - if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) ) + if ( countDownToZero( notifyStreamsToSkipTestsJustNow ) ) { builder.getCachableCommands().skipSinceNextTest(); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/pom.xml ---------------------------------------------------------------------- diff --git a/surefire-api/pom.xml b/surefire-api/pom.xml index 6f66e66..3567b93 100644 --- a/surefire-api/pom.xml +++ b/surefire-api/pom.xml @@ -42,6 +42,12 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <redirectTestOutputToFile>true</redirectTestOutputToFile> + <includes> + <include>**/JUnit4SuiteTest.java</include> + </includes> + </configuration> <dependencies> <dependency> <groupId>org.apache.maven.surefire</groupId> http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java new file mode 100644 index 0000000..6cfc6bf --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java @@ -0,0 +1,64 @@ +package org.apache.maven.surefire.util.internal; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Concurrency utilities. + * + * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> + * @since 2.19 + */ +public final class ConcurrencyUtils +{ + private ConcurrencyUtils() + { + throw new IllegalStateException( "not instantiable constructor" ); + } + + /** + * Decreases {@code counter} to zero, or does not change the counter if negative. + * This method pretends been atomic. Only one thread can succeed setting the counter to zero. + * + * @param counter atomic counter + * @return {@code true} if this Thread modified concurrent counter from any positive number down to zero. + */ + @SuppressWarnings( "checkstyle:emptyforiteratorpad" ) + public static boolean countDownToZero( AtomicInteger counter ) + { + for (;;) + { + int c = counter.get(); + if ( c > 0 ) + { + int newCounter = c - 1; + if ( counter.compareAndSet( c, newCounter ) ) + { + return newCounter == 0; + } + } + else + { + return false; + } + } + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java new file mode 100644 index 0000000..c2ec153 --- /dev/null +++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java @@ -0,0 +1,78 @@ +package org.apache.maven; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import junit.framework.JUnit4TestAdapter; +import junit.framework.Test; +import org.apache.maven.plugin.surefire.runorder.ThreadedExecutionSchedulerTest; +import org.apache.maven.surefire.SpecificTestClassFilterTest; +import org.apache.maven.surefire.booter.ForkingRunListenerTest; +import org.apache.maven.surefire.booter.MasterProcessCommandTest; +import org.apache.maven.surefire.booter.SurefireReflectorTest; +import org.apache.maven.surefire.report.LegacyPojoStackTraceWriterTest; +import org.apache.maven.surefire.suite.RunResultTest; +import org.apache.maven.surefire.testset.ResolvedTestTest; +import org.apache.maven.surefire.testset.TestListResolverTest; +import org.apache.maven.surefire.util.DefaultDirectoryScannerTest; +import org.apache.maven.surefire.util.RunOrderCalculatorTest; +import org.apache.maven.surefire.util.RunOrderTest; +import org.apache.maven.surefire.util.ScanResultTest; +import org.apache.maven.surefire.util.TestsToRunTest; +import org.apache.maven.surefire.util.UrlUtilsTest; +import org.apache.maven.surefire.util.internal.ByteBufferTest; +import org.apache.maven.surefire.util.internal.ConcurrencyUtilsTest; +import org.apache.maven.surefire.util.internal.StringUtilsTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. + * + * @author Tibor Digana (tibor17) + * @since 2.19 + */ +@Suite.SuiteClasses( { + ThreadedExecutionSchedulerTest.class, + ForkingRunListenerTest.class, + MasterProcessCommandTest.class, + SurefireReflectorTest.class, + LegacyPojoStackTraceWriterTest.class, + RunResultTest.class, + ResolvedTestTest.class, + TestListResolverTest.class, + ByteBufferTest.class, + ConcurrencyUtilsTest.class, + StringUtilsTest.class, + DefaultDirectoryScannerTest.class, + RunOrderCalculatorTest.class, + RunOrderTest.class, + ScanResultTest.class, + TestsToRunTest.class, + UrlUtilsTest.class, + SpecificTestClassFilterTest.class +} ) +@RunWith( Suite.class ) +public class JUnit4SuiteTest +{ + public static Test suite() + { + return new JUnit4TestAdapter( JUnit4SuiteTest.class ); + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java new file mode 100644 index 0000000..516f885 --- /dev/null +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java @@ -0,0 +1,104 @@ +package org.apache.maven.surefire.util.internal; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.junit.Test; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +/** + * Concurrency utilities. + * + * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> + * @since 2.19 + */ +public class ConcurrencyUtilsTest +{ + + @Test + public void countDownShouldBeUnchangedAsZero$NegativeTest() + { + AtomicInteger atomicCounter = new AtomicInteger( 0 ); + assertFalse( countDownToZero( atomicCounter ) ); + assertThat( atomicCounter.get(), is( 0 ) ); + } + + @Test + public void countDownShouldBeUnchangedAsNegative$NegativeTest() + { + AtomicInteger atomicCounter = new AtomicInteger( -1 ); + assertFalse( countDownToZero( atomicCounter ) ); + assertThat( atomicCounter.get(), is( -1 ) ); + } + + @Test + public void countDownShouldBeDecreasedByOneThreadModification() + { + AtomicInteger atomicCounter = new AtomicInteger( 10 ); + assertFalse( countDownToZero( atomicCounter ) ); + assertThat( atomicCounter.get(), is( 9 ) ); + } + + @Test + public void countDownToZeroShouldBeDecreasedByOneThreadModification() + { + AtomicInteger atomicCounter = new AtomicInteger( 1 ); + assertTrue( countDownToZero( atomicCounter ) ); + assertThat( atomicCounter.get(), is( 0 ) ); + } + + @Test + public void countDownShouldBeDecreasedByTwoThreadsModification() + throws ExecutionException, InterruptedException + { + final AtomicInteger atomicCounter = new AtomicInteger( 3 ); + + FutureTask<Boolean> task = new FutureTask<Boolean>( new Callable<Boolean>() + { + public Boolean call() + throws Exception + { + return countDownToZero( atomicCounter ); + } + } ); + Thread t = new Thread( task ); + t.start(); + + assertFalse( countDownToZero( atomicCounter ) ); + + assertFalse( task.get() ); + + assertThat( atomicCounter.get(), is( 1 ) ); + + assertTrue( countDownToZero( atomicCounter ) ); + + assertThat( atomicCounter.get(), is( 0 ) ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java ---------------------------------------------------------------------- diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java index e9136e1..5748e4b 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java @@ -25,6 +25,9 @@ import org.junit.runner.notification.RunNotifier; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; /** * Extends {@link RunNotifier JUnit notifier}, @@ -35,31 +38,29 @@ import java.util.Iterator; * @since 2.19 */ public class Notifier - extends RunNotifier + extends RunNotifier implements Stoppable { private final Collection<RunListener> listeners = new ArrayList<RunListener>(); - private JUnit4RunListener reporter; + private final AtomicInteger skipAfterFailureCount; - @Override - public void pleaseStop() + private final JUnit4RunListener reporter; + + public Notifier( JUnit4RunListener reporter, int skipAfterFailureCount ) { - super.pleaseStop(); - reporter.testExecutionSkippedByUser(); + addListener( reporter ); + this.reporter = reporter; + this.skipAfterFailureCount = new AtomicInteger( skipAfterFailureCount ); } - /** - * Adds reporter listener to the bottom of queue and retrieves old reporter if any exists. - * - * @param reporter registered listener - * @return old listener; or null if did not exist - */ - public JUnit4RunListener setReporter( JUnit4RunListener reporter ) + public void fireStopEvent() { - JUnit4RunListener old = this.reporter; - this.reporter = reporter; - addListener( reporter ); - return old; + if ( countDownToZero( skipAfterFailureCount ) ) + { + pleaseStop(); + } + + reporter.testExecutionSkippedByUser(); } @Override http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java ---------------------------------------------------------------------- diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java new file mode 100644 index 0000000..376d631 --- /dev/null +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java @@ -0,0 +1,35 @@ +package org.apache.maven.surefire.common.junit4; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Covers configuration parameter <em>skipAfterFailureCount</em>. + * + * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> + * @since 2.19 + * @see org.apache.maven.surefire.common.junit4.Notifier + */ +public interface Stoppable +{ + /** + * Fire stop even to plugin process and/or call {@link org.junit.runner.notification.RunNotifier#pleaseStop()}. + */ + void fireStopEvent(); +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java index d45b678..84346e7 100644 --- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java +++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java @@ -19,12 +19,13 @@ package org.apache.maven.surefire.junit4; * under the License. */ +import org.apache.maven.surefire.common.junit4.Notifier; +import org.apache.maven.surefire.common.junit4.Stoppable; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; /** - * Calling {@link RunNotifier#pleaseStop()} if failure appeared. + * Calling {@link Notifier#fireStopEvent()} if failure happens. * * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> * @since 2.19 @@ -32,17 +33,17 @@ import org.junit.runner.notification.RunNotifier; final class JUnit4FailFastListener extends RunListener { - private final RunNotifier notifier; + private final Stoppable stoppable; - JUnit4FailFastListener( RunNotifier notifier ) + JUnit4FailFastListener( Notifier stoppable ) { - this.notifier = notifier; + this.stoppable = stoppable; } @Override public void testFailure( Failure failure ) throws Exception { - notifier.pleaseStop(); + stoppable.fireStopEvent(); } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java index e8f041d..2276eac 100644 --- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java +++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java @@ -146,8 +146,7 @@ public class JUnit4Provider startCapture( (ConsoleOutputReceiver) reporter ); - Notifier notifier = new Notifier(); - notifier.setReporter( new JUnit4RunListener( reporter ) ); + Notifier notifier = new Notifier( new JUnit4RunListener( reporter ), getSkipAfterFailureCount() ); if ( isFailFast() ) { notifier.addListener( new JUnit4FailFastListener( notifier ) ); @@ -193,6 +192,11 @@ public class JUnit4Provider return providerParameters.getSkipAfterFailureCount() > 0; } + private int getSkipAfterFailureCount() + { + return isFailFast() && !isRerunFailingTests() ? providerParameters.getSkipAfterFailureCount() : 0; + } + private void closeCommandsReader() { if ( commandsReader != null ) @@ -227,7 +231,8 @@ public class JUnit4Provider if ( isFailFast() && e instanceof StoppedByUserException ) { String reason = e.getClass().getName(); - notifier.fireTestIgnored( createDescription( clazz.getName(), createIgnored( reason ) ) ); + Description skippedTest = createDescription( clazz.getName(), createIgnored( reason ) ); + notifier.fireTestIgnored( skippedTest ); } else { http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java index dda6b68..0f6efc9 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java @@ -19,6 +19,7 @@ package org.apache.maven.surefire.junitcore; * under the License. */ +import org.apache.maven.surefire.common.junit4.Stoppable; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; @@ -27,7 +28,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** - * Calling {@link Stoppable#pleaseStop()} if failure appeared. + * Calling {@link Stoppable#fireStopEvent()} if failure happens. * * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> * @since 2.19 @@ -60,6 +61,6 @@ final class JUnit47FailFastListener public void testFailure( Failure failure ) throws Exception { - stoppable.pleaseStop(); + stoppable.fireStopEvent(); } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java index 7f1a03a..9935d9a 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java @@ -29,15 +29,12 @@ import org.junit.runner.notification.RunListener; * JUnitCore solves bugs in original junit class {@link org.junit.runner.JUnitCore}.<p> * The notifier method {@link org.junit.runner.notification.RunNotifier#fireTestRunFinished} * is called anyway in finally block. - * This class provides method {@link #pleaseStop()} without any need to retrieve - * {@link org.junit.runner.notification.RunNotifier} outside. * * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> * @since 2.19 * @see https://github.com/junit-team/junit/issues/1186 */ class JUnitCore - implements Stoppable { private final Notifier notifier; @@ -79,12 +76,4 @@ class JUnitCore protected void afterFinished() { } - - /** - * {@inheritDoc} - */ - public void pleaseStop() - { - notifier.pleaseStop(); - } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java index 243cca0..29687ef 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java @@ -145,8 +145,8 @@ public class JUnitCoreProvider } } - Notifier notifier = new Notifier(); - notifier.setReporter( createRunListener( reporterFactory, consoleLogger ) ); + Notifier notifier = + new Notifier( createRunListener( reporterFactory, consoleLogger ), getSkipAfterFailureCount() ); // Add test failure listener JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener(); @@ -195,6 +195,11 @@ public class JUnitCoreProvider return providerParameters.getSkipAfterFailureCount() > 0; } + private int getSkipAfterFailureCount() + { + return isFailFast() && !isRerunFailingTests() ? providerParameters.getSkipAfterFailureCount() : 0; + } + private void closeCommandsReader() { if ( commandsReader != null ) http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java index e0c9f9e..eb41217 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java @@ -27,6 +27,7 @@ import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.TestsToRun; import org.junit.Ignore; import org.junit.runner.Computer; +import org.junit.runner.Description; import org.junit.runner.Request; import org.junit.runner.Result; import org.junit.runner.manipulation.Filter; @@ -36,7 +37,6 @@ import org.junit.runner.notification.StoppedByUserException; import java.util.Collection; import java.util.Collections; import java.util.Queue; -import java.util.Random; import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createDescription; import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createIgnored; @@ -54,8 +54,6 @@ final class JUnitCoreWrapper private final ConsoleLogger logger; private final boolean failFast; - private Object o = new Random().nextInt(); - JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger logger, boolean failFast ) { @@ -86,7 +84,7 @@ final class JUnitCoreWrapper private JUnitCore createJUnitCore( final Notifier notifier, Collection<RunListener> listeners ) { - JUnitCore junitCore = new JUnitCore( notifier ); + JUnitCore junitCore = new JUnitCore(); // custom listeners added last notifier.addListeners( listeners ); @@ -154,10 +152,10 @@ final class JUnitCoreWrapper { private final JUnit47FailFastListener failFastListener; - JUnitCore( Notifier notifier ) + JUnitCore() { super( notifier ); - failFastListener = failFast ? new JUnit47FailFastListener( this ) : null; + failFastListener = failFast ? new JUnit47FailFastListener( notifier ) : null; if ( failFastListener != null ) { notifier.addListener( failFastListener ); @@ -188,10 +186,11 @@ final class JUnitCoreWrapper if ( stoppedTests != null ) { String reason = e.getClass().getName(); - Ignore reasonForIgnoredTest = createIgnored( reason ); + Ignore reasonForSkippedTest = createIgnored( reason ); for ( String clazz; ( clazz = stoppedTests.poll() ) != null; ) { - notifier.fireTestIgnored( createDescription( clazz, reasonForIgnoredTest ) ); + Description skippedTest = createDescription( clazz, reasonForSkippedTest ); + notifier.fireTestIgnored( skippedTest ); } } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java deleted file mode 100644 index 2450e64..0000000 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.apache.maven.surefire.junitcore; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -/** - * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> - * @since 2.19 - */ -interface Stoppable -{ - /** - * Delegates this call to {@link org.junit.runner.notification.RunNotifier#pleaseStop()}. - */ - void pleaseStop(); -} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java index d3d5c00..91f3461 100644 --- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java +++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java @@ -51,8 +51,7 @@ public class FailFastListener public void onTestFailure( ITestResult result ) { - FailFastEventsSingleton.getInstance().setSkipOnNextTest(); - stoppable.pleaseStop(); + stoppable.fireStopEvent(); } public void onTestSkipped( ITestResult result ) http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java index c7be682..dd172d2 100644 --- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java +++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java @@ -20,6 +20,8 @@ package org.apache.maven.surefire.testng.utils; */ /** + * Covers configuration parameter <em>skipAfterFailureCount</em>. + * * @author <a href="mailto:tibordig...@apache.org">Tibor Digana (tibor17)</a> * @since 2.19 */ @@ -28,5 +30,5 @@ public interface Stoppable /** * Delegates this call to {@link org.apache.maven.surefire.report.RunListener#testExecutionSkippedByUser()}. */ - void pleaseStop(); + void fireStopEvent(); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java index 5297276..a721bbc 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java @@ -79,11 +79,12 @@ public class TestNGDirectoryTestSuite private final List<CommandLineOption> mainCliOptions; - private final boolean isFailFast; + private final int skipAfterFailureCount; public TestNGDirectoryTestSuite( String testSourceDirectory, Map<String, String> confOptions, File reportsDirectory, TestListResolver methodFilter, RunOrderCalculator runOrderCalculator, - ScanResult scanResult, List<CommandLineOption> mainCliOptions, boolean isFailFast ) + ScanResult scanResult, List<CommandLineOption> mainCliOptions, + int skipAfterFailureCount ) { this.runOrderCalculator = runOrderCalculator; this.options = confOptions; @@ -96,7 +97,7 @@ public class TestNGDirectoryTestSuite this.junitTestAnnotation = findJUnitTestAnnotation(); this.junitOptions = createJUnitOptions(); this.mainCliOptions = mainCliOptions; - this.isFailFast = isFailFast; + this.skipAfterFailureCount = skipAfterFailureCount; } public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory ) @@ -131,7 +132,7 @@ public class TestNGDirectoryTestSuite final Map<String, String> optionsToUse = isJUnitTest( testClass ) ? junitOptions : options; TestNGExecutor.run( new Class<?>[]{ testClass }, testSourceDirectory, optionsToUse, reporter, this, - reportsDirectory, methodFilter, mainCliOptions, isFailFast ); + reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); finishTestSuite( reporter, this ); } @@ -221,14 +222,14 @@ public class TestNGDirectoryTestSuite Class<?>[] testClasses = testNgTestClasses.toArray( new Class<?>[testNgTestClasses.size()] ); TestNGExecutor.run( testClasses, testSourceDirectory, options, reporterManager, this, - testNgReportsDirectory, methodFilter, mainCliOptions, isFailFast ); + testNgReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); if ( !junitTestClasses.isEmpty() ) { testClasses = junitTestClasses.toArray( new Class[junitTestClasses.size()] ); TestNGExecutor.run( testClasses, testSourceDirectory, junitOptions, reporterManager, this, - junitReportsDirectory, methodFilter, mainCliOptions, isFailFast ); + junitReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); } finishTestSuite( reporterManager, this ); @@ -298,7 +299,7 @@ public class TestNGDirectoryTestSuite startTestSuite( reporter, this ); TestNGExecutor.run( new Class<?>[] { testSet.getTestClass() }, testSourceDirectory, options, reporter, - this, reportsDirectory, methodFilter, mainCliOptions, isFailFast ); + this, reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); finishTestSuite( reporter, this ); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java index d481bb2..5a91db0 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java @@ -23,6 +23,7 @@ import org.apache.maven.surefire.booter.ProviderParameterNames; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.testng.conf.Configurator; +import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton; import org.apache.maven.surefire.testng.utils.FailFastListener; import org.apache.maven.surefire.testng.utils.Stoppable; import org.apache.maven.surefire.testset.TestListResolver; @@ -45,8 +46,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import static org.apache.maven.surefire.util.ReflectionUtils.instantiate; +import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; /** * Contains utility methods for executing TestNG. @@ -73,7 +76,8 @@ public class TestNGExecutor public static void run( Class<?>[] testClasses, String testSourceDirectory, Map<String, String> options, // string,string because TestNGMapConfigurator#configure() RunListener reportManager, TestNgTestSuite suite, File reportsDirectory, - TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, boolean isFailFast ) + TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, + int skipAfterFailureCount ) throws TestSetFailedException { TestNG testng = new TestNG( true ); @@ -123,7 +127,7 @@ public class TestNGExecutor testng.setXmlSuites( xmlSuites ); configurator.configure( testng, options ); - postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast ); + postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, skipAfterFailureCount ); testng.run(); } @@ -265,13 +269,13 @@ public class TestNGExecutor public static void run( List<String> suiteFiles, String testSourceDirectory, Map<String, String> options, // string,string because TestNGMapConfigurator#configure() RunListener reportManager, TestNgTestSuite suite, File reportsDirectory, - boolean isFailFast ) + int skipAfterFailureCount ) throws TestSetFailedException { TestNG testng = new TestNG( true ); Configurator configurator = getConfigurator( options.get( "testng.configurator" ) ); configurator.configure( testng, options ); - postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast ); + postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, skipAfterFailureCount ); testng.setTestSuites( suiteFiles ); testng.run(); } @@ -297,7 +301,7 @@ public class TestNGExecutor } private static void postConfigure( TestNG testNG, String sourcePath, final RunListener reportManager, - TestNgTestSuite suite, File reportsDirectory, boolean skipAfterFailure ) + TestNgTestSuite suite, File reportsDirectory, int skipAfterFailureCount ) throws TestSetFailedException { // turn off all TestNG output @@ -306,19 +310,12 @@ public class TestNGExecutor TestNGReporter reporter = createTestNGReporter( reportManager, suite ); testNG.addListener( (Object) reporter ); - if ( skipAfterFailure ) + if ( skipAfterFailureCount > 0 ) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); testNG.addListener( instantiate( cl, "org.apache.maven.surefire.testng.utils.FailFastNotifier", Object.class ) ); - Stoppable stoppable = new Stoppable() - { - public void pleaseStop() - { - reportManager.testExecutionSkippedByUser(); - } - }; - testNG.addListener( new FailFastListener( stoppable ) ); + testNG.addListener( new FailFastListener( createStoppable( reportManager, skipAfterFailureCount ) ) ); } // FIXME: use classifier to decide if we need to pass along the source dir (only for JDK14) @@ -330,6 +327,24 @@ public class TestNGExecutor testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() ); } + private static Stoppable createStoppable( final RunListener reportManager, int skipAfterFailureCount ) + { + final AtomicInteger currentFaultCount = new AtomicInteger( skipAfterFailureCount ); + + return new Stoppable() + { + public void fireStopEvent() + { + if ( countDownToZero( currentFaultCount ) ) + { + FailFastEventsSingleton.getInstance().setSkipOnNextTest(); + } + + reportManager.testExecutionSkippedByUser(); + } + }; + } + // If we have access to IResultListener, return a ConfigurationAwareTestNGReporter // But don't cause NoClassDefFoundErrors if it isn't available; just return a regular TestNGReporter instead private static TestNGReporter createTestNGReporter( RunListener reportManager, TestNgTestSuite suite ) http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java index 8777ceb..77b5c75 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java @@ -149,6 +149,11 @@ public class TestNGProvider return providerParameters.getSkipAfterFailureCount() > 0; } + private int getSkipAfterFailureCount() + { + return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0; + } + private void closeCommandsReader() { if ( commandsReader != null ) @@ -174,7 +179,8 @@ public class TestNGProvider { return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties, reporterConfiguration.getReportsDirectory(), createMethodFilter(), - runOrderCalculator, scanResult, mainCliOptions, isFailFast() ); + runOrderCalculator, scanResult, mainCliOptions, + getSkipAfterFailureCount() ); } private TestNGXmlTestSuite newXmlSuite() @@ -182,7 +188,7 @@ public class TestNGProvider return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(), testRequest.getTestSourceDirectory().toString(), providerProperties, - reporterConfiguration.getReportsDirectory(), isFailFast() ); + reporterConfiguration.getReportsDirectory(), getSkipAfterFailureCount() ); } @SuppressWarnings( "unchecked" ) http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java ---------------------------------------------------------------------- diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java index bf105fe..ab9ae7f 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java @@ -49,7 +49,7 @@ public class TestNGXmlTestSuite private final File reportsDirectory; - private final boolean isFailFast; + private final int skipAfterFailureCount; // Not really used private Map<File, String> testSets; @@ -59,13 +59,13 @@ public class TestNGXmlTestSuite * xml file(s). The XML files are suite definitions files according to TestNG DTD. */ public TestNGXmlTestSuite( List<File> suiteFiles, String testSourceDirectory, Map<String, String> confOptions, - File reportsDirectory, boolean isFailFast ) + File reportsDirectory, int skipAfterFailureCount ) { this.suiteFiles = suiteFiles; this.options = confOptions; this.testSourceDirectory = testSourceDirectory; this.reportsDirectory = reportsDirectory; - this.isFailFast = isFailFast; + this.skipAfterFailureCount = skipAfterFailureCount; } public void execute( ReporterFactory reporterManagerFactory ) @@ -81,7 +81,7 @@ public class TestNGXmlTestSuite TestNGDirectoryTestSuite.startTestSuite( reporter, this ); TestNGExecutor.run( suiteFilePaths, testSourceDirectory, options, reporter, this, reportsDirectory, - isFailFast ); + skipAfterFailureCount ); TestNGDirectoryTestSuite.finishTestSuite( reporter, this ); }