Author: krosenvold
Date: Fri Nov  5 17:43:24 2010
New Revision: 1031678

URL: http://svn.apache.org/viewvc?rev=1031678&view=rev
Log:
[SUREFIRE-658] Removed synchronization on ReporterManager

     - TestNG provider retains existing synchronization through wrapper class.
     - JUnit4/3 lose synchronization on the reporter manager.
     - Junit4.7 run with per-thread instance of ReporterManager.

Added:
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
   (with props)
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
   (with props)
    
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java
   (with props)
Modified:
    
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/report/ReporterManager.java
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListenerTest.java
    
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
    
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java

Modified: 
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/report/ReporterManager.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/report/ReporterManager.java?rev=1031678&r1=1031677&r2=1031678&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/report/ReporterManager.java
 (original)
+++ 
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/report/ReporterManager.java
 Fri Nov  5 17:43:24 2010
@@ -27,28 +27,14 @@ import java.util.List;
  * <p/>
  * Synchronization/Threading note:
  * <p/>
- * This design is really only good for single-threaded test execution. 
Although it is currently
- * used by multi-threaded providers too, the design does not really make sense 
(and is probably buggy).
+ * This design is really only good for single-threaded test execution. With 
the use of the additional
+ * SynchronizedReporterManager you can get a buggy version that sort-of 
supports multithreading.
  * <p/>
- * This is because to get correct results, the client basically needs to do 
something like this:
- * synchronized( ReporterManger.getClass()){
- * reporterManager.runStarted()
- * reporterManager.testSetStarting()
- * reporterManager.testStarting()
- * reporterManager.testSucceeded()
- * reporterManager.testSetCompleted()
- * reporterManager.runCompleted()
- * }
- * <p/>
- * This is because the underlying providers are singletons and keep state, if 
you remove the outer synchronized
- * block, you may get mixups between results from different tests; although 
the end result (total test count etc)
- * should probably be correct.
+ * The underlying providers are singletons and keep state per ReporterManager 
instance
  * <p/>
  * The solution to this problem involves making a clearer separation between 
test-result collection and reporting,
  * preferably removing singleton state approach out of the reporting interface.
  * <p/>
- * Please also note that the synchronization requirements of this interface 
severely limit the concurrency
- * potential of all the parallel surefire providers, especially when runnning 
non-io bound tests,
  */
 public class ReporterManager
 {
@@ -56,20 +42,28 @@ public class ReporterManager
 
     private final MulticastingReporter multicastingReporter;
 
-    private final SystemStreamCapturer consoleCapturer = new 
SystemStreamCapturer();
+    private final SystemStreamCapturer consoleCapturer;
 
     public ReporterManager( List reports, RunStatistics runStatisticsForThis )
     {
+        this.consoleCapturer =  new SystemStreamCapturer();
         multicastingReporter = new MulticastingReporter( reports );
         this.runStatisticsForThis = runStatisticsForThis;
     }
 
-    public synchronized void writeMessage( String message )
+    protected ReporterManager( ReporterManager other )
+    {
+        this.multicastingReporter = other.multicastingReporter;
+        this.runStatisticsForThis = other.runStatisticsForThis;
+        this.consoleCapturer =  other.consoleCapturer;
+    }
+
+    public void writeMessage( String message )
     {
         multicastingReporter.writeMessage( message );
     }
-    
-    public synchronized void writeConsoleMessage( String message )
+
+    public void writeConsoleMessage( String message )
     {
         multicastingReporter.writeConsoleMessage( message );
     }
@@ -78,12 +72,12 @@ public class ReporterManager
     // Run
     // ----------------------------------------------------------------------
 
-    public synchronized void runStarting()
+    public void runStarting()
     {
         multicastingReporter.runStarting();
     }
 
-    public synchronized void runCompleted()
+    public void runCompleted()
     {
         multicastingReporter.runCompleted();
         multicastingReporter.writeFooter( "" );
@@ -112,19 +106,19 @@ public class ReporterManager
         consoleCapturer.restoreStreams();
     }
 
-    public synchronized void writeFooter( String footer )
+    public void writeFooter( String footer )
     {
         multicastingReporter.writeFooter( footer );
     }
 
 
-    public synchronized void testSetStarting( ReportEntry report )
+    public void testSetStarting( ReportEntry report )
         throws ReporterException
     {
         multicastingReporter.testSetStarting( report );
     }
 
-    public synchronized void testSetCompleted( ReportEntry report )
+    public void testSetCompleted( ReportEntry report )
     {
         multicastingReporter.testSetCompleted( report );
     }
@@ -133,24 +127,24 @@ public class ReporterManager
     // Test
     // ----------------------------------------------------------------------
 
-    public synchronized void testStarting( ReportEntry report )
+    public void testStarting( ReportEntry report )
     {
         multicastingReporter.testStarting( report );
     }
 
-    public synchronized void testSucceeded( ReportEntry report )
+    public void testSucceeded( ReportEntry report )
     {
         consoleCapturer.clearCapturedContent();
         runStatisticsForThis.incrementCompletedCount();
         multicastingReporter.testSucceeded( report );
     }
 
-    public synchronized void testError( ReportEntry reportEntry )
+    public void testError( ReportEntry reportEntry )
     {
         testError( reportEntry, consoleCapturer.getStdOutLog(), 
consoleCapturer.getStdErrLog() );
     }
 
-    public synchronized void testError( ReportEntry reportEntry, String 
stdOutLog, String stdErrLog )
+    public void testError( ReportEntry reportEntry, String stdOutLog, String 
stdErrLog )
     {
         multicastingReporter.testError( reportEntry, stdOutLog, stdErrLog );
         runStatisticsForThis.incrementErrorsCount();
@@ -159,13 +153,13 @@ public class ReporterManager
         consoleCapturer.clearCapturedContent();
     }
 
-    public synchronized void testFailed( ReportEntry reportEntry )
+    public void testFailed( ReportEntry reportEntry )
     {
         testFailed( reportEntry, consoleCapturer.getStdOutLog(), 
consoleCapturer.getStdErrLog() );
     }
 
 
-    public synchronized void testFailed( ReportEntry reportEntry, String 
stdOutLog, String stdErrLog )
+    public void testFailed( ReportEntry reportEntry, String stdOutLog, String 
stdErrLog )
     {
         multicastingReporter.testFailed( reportEntry, stdOutLog, stdErrLog );
         runStatisticsForThis.incrementFailureCount();
@@ -178,7 +172,7 @@ public class ReporterManager
     // Counters
     // ----------------------------------------------------------------------
 
-    public synchronized void testSkipped( ReportEntry report )
+    public void testSkipped( ReportEntry report )
     {
         consoleCapturer.clearCapturedContent();
         runStatisticsForThis.incrementSkippedCount();
@@ -186,7 +180,7 @@ public class ReporterManager
         multicastingReporter.testSkipped( report );
     }
 
-    public synchronized void reset()
+    public void reset()
     {
         multicastingReporter.reset();
     }

Added: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java?rev=1031678&view=auto
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
 (added)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
 Fri Nov  5 17:43:24 2010
@@ -0,0 +1,46 @@
+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.
+ */
+
+import org.apache.maven.surefire.report.ReporterManagerFactory;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+
+/**
+* @author Kristian Rosenvold
+*/
+public class ClassesParallelRunListener
+    extends ConcurrentReportingRunListener
+{
+    public ClassesParallelRunListener( ReporterManagerFactory reporterFactory )
+        throws TestSetFailedException
+    {
+        super( reporterFactory, false );
+    }
+
+    @Override
+    public void checkIfTestSetCanBeReported( TestSet testSetForTest )
+        throws TestSetFailedException
+    {
+        TestSet currentlyAttached = TestSet.getThreadTestSet();
+        if ( currentlyAttached != null && currentlyAttached != testSetForTest )
+        {
+            currentlyAttached.setAllScheduled( getReporterManager() );
+        }
+    }
+}

Propchange: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java?rev=1031678&r1=1031677&r2=1031678&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
 (original)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
 Fri Nov  5 17:43:24 2010
@@ -42,18 +42,24 @@ public abstract class ConcurrentReportin
 
     protected Map<Class, TestSet> classMethodCounts = new 
ConcurrentHashMap<Class, TestSet>();
 
-    protected final ReporterManager reporterManager;
+    private final ThreadLocal<ReporterManager> reporterManagerThreadLocal = 
new ThreadLocal<ReporterManager>();
 
     protected final boolean reportImmediately;
 
     private final ConcurrentPrintStream out = new ConcurrentPrintStream( true 
);
+
     private final ConcurrentPrintStream err = new ConcurrentPrintStream( false 
);
 
+    private ReporterManagerFactory reporterFactory;
+
     public ConcurrentReportingRunListener( ReporterManagerFactory 
reporterFactory, boolean reportImmediately )
         throws TestSetFailedException
     {
         this.reportImmediately = reportImmediately;
-        reporterManager = reporterFactory.createReporterManager();
+        this.reporterFactory = reporterFactory;
+        // We must create the first reporterManager here, even though we will 
never use it.
+        // There is some room for improvement here
+        this.reporterFactory.createReporterManager();
         // Important: We must capture System.out/System.err AFTER the  
reportManager captures stdout/stderr
         // because we know how to demultiplex correctly. The redirection in 
reporterManager is basically
         // ignored/unused because we use ConcurrentPrintStream.
@@ -61,6 +67,31 @@ public abstract class ConcurrentReportin
         System.setErr( err );
     }
 
+
+    protected ReporterManager getReporterManager()
+        throws TestSetFailedException
+    {
+        ReporterManager reporterManager = reporterManagerThreadLocal.get();
+        if ( reporterManager == null )
+        {
+            reporterManager = reporterFactory.createReporterManager();
+            reporterManagerThreadLocal.set( reporterManager );
+        }
+        return reporterManager;
+    }
+
+    public static ConcurrentReportingRunListener createInstance( 
ReporterManagerFactory reporterManagerFactory,
+                                                                 boolean 
parallelClasses, boolean parallelBoth )
+        throws TestSetFailedException
+    {
+        if ( parallelClasses )
+        {
+            return new ClassesParallelRunListener( reporterManagerFactory );
+        }
+        return new MethodsParallelRunListener( reporterManagerFactory, 
!parallelBoth );
+    }
+
+
     @Override
     public void testRunStarted( Description description )
         throws Exception
@@ -74,13 +105,13 @@ public abstract class ConcurrentReportin
     {
         for ( TestSet testSet : classMethodCounts.values() )
         {
-            testSet.replay( reporterManager );
+            testSet.replay( getReporterManager() );
         }
         System.setOut( orgSystemOut );
         System.setErr( orgSystemErr );
 
-        out.writeTo(  orgSystemOut );
-        err.writeTo(  orgSystemErr );
+        out.writeTo( orgSystemOut );
+        err.writeTo( orgSystemErr );
     }
 
     protected TestMethod getTestMethod()
@@ -102,13 +133,14 @@ public abstract class ConcurrentReportin
     public void testFailure( Failure failure )
         throws Exception
     {
-        getOrCreateTestMethod(failure.getDescription()).testFailure( failure );
+        getOrCreateTestMethod( failure.getDescription() ).testFailure( failure 
);
     }
 
     private TestMethod getOrCreateTestMethod( Description description )
     {
         TestMethod threadTestMethod = TestMethod.getThreadTestMethod();
-        if (threadTestMethod != null){
+        if ( threadTestMethod != null )
+        {
             return threadTestMethod;
         }
         TestSet testSet = getTestSet( description );
@@ -128,7 +160,7 @@ public abstract class ConcurrentReportin
         TestSet testSet = getTestSet( description );
         TestMethod testMethod = getTestSet( description ).createTestMethod( 
description );
         testMethod.testIgnored( description );
-        testSet.incrementFinishedTests( reporterManager, reportImmediately );
+        testSet.incrementFinishedTests( getReporterManager(), 
reportImmediately );
     }
 
     @Override
@@ -141,75 +173,17 @@ public abstract class ConcurrentReportin
         testSet.attachToThread();
     }
 
-    public abstract void checkIfTestSetCanBeReported( TestSet testSetForTest );
+    public abstract void checkIfTestSetCanBeReported( TestSet testSetForTest )
+        throws TestSetFailedException;
 
     @Override
     public void testFinished( Description description )
         throws Exception
     {
         getTestMethod().testFinished();
-        TestSet.getThreadTestSet().incrementFinishedTests( reporterManager, 
reportImmediately );
+        TestSet.getThreadTestSet().incrementFinishedTests( 
getReporterManager(), reportImmediately );
         detachTestMethodFromThread();
     }
 
-    public static ConcurrentReportingRunListener createInstance( 
ReporterManagerFactory reporterManagerFactory,
-                                                                 boolean 
parallelClasses, boolean parallelBoth )
-        throws TestSetFailedException
-    {
-        if ( parallelClasses )
-        {
-            return new ClassesParallelRunListener( reporterManagerFactory );
-        }
-        return new MethodsParallelRunListener( reporterManagerFactory, 
!parallelBoth );
-    }
-
-    public static class ClassesParallelRunListener
-        extends ConcurrentReportingRunListener
-    {
-        public ClassesParallelRunListener( ReporterManagerFactory 
reporterFactory )
-            throws TestSetFailedException
-        {
-            super( reporterFactory, false );
-        }
-
-        @Override
-        public void checkIfTestSetCanBeReported( TestSet testSetForTest )
-        {
-            TestSet currentlyAttached = TestSet.getThreadTestSet();
-            if ( currentlyAttached != null && currentlyAttached != 
testSetForTest )
-            {
-                currentlyAttached.setAllScheduled( reporterManager );
-            }
-        }
-    }
-
-    public static class MethodsParallelRunListener
-        extends ConcurrentReportingRunListener
-    {
-        private volatile TestSet lastStarted;
-
-        private final Object lock = new Object();
 
-        public MethodsParallelRunListener( ReporterManagerFactory 
reporterFactory, boolean reportImmediately )
-            throws TestSetFailedException
-        {
-            super( reporterFactory, reportImmediately );
-        }
-
-        @Override
-        public void checkIfTestSetCanBeReported( TestSet testSetForTest )
-        {
-            synchronized ( lock )
-            {
-                if ( testSetForTest != lastStarted )
-                {
-                    if ( lastStarted != null )
-                    {
-                        lastStarted.setAllScheduled( reporterManager );
-                    }
-                    lastStarted = testSetForTest;
-                }
-            }
-        }
-    }
 }

Added: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java?rev=1031678&view=auto
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
 (added)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
 Fri Nov  5 17:43:24 2010
@@ -0,0 +1,56 @@
+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.
+ */
+
+import org.apache.maven.surefire.report.ReporterManagerFactory;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+
+/**
+* @author Kristian Rosenvold
+*/
+public class MethodsParallelRunListener
+    extends ConcurrentReportingRunListener
+{
+    private volatile TestSet lastStarted;
+
+    private final Object lock = new Object();
+
+    public MethodsParallelRunListener( ReporterManagerFactory reporterFactory, 
boolean reportImmediately )
+        throws TestSetFailedException
+    {
+        super( reporterFactory, reportImmediately );
+    }
+
+    @Override
+    public void checkIfTestSetCanBeReported( TestSet testSetForTest )
+        throws TestSetFailedException
+    {
+        synchronized ( lock )
+        {
+            if ( testSetForTest != lastStarted )
+            {
+                if ( lastStarted != null )
+                {
+                    lastStarted.setAllScheduled( getReporterManager() );
+                }
+                lastStarted = testSetForTest;
+            }
+        }
+    }
+}

Propchange: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListenerTest.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListenerTest.java?rev=1031678&r1=1031677&r2=1031678&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListenerTest.java
 (original)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListenerTest.java
 Fri Nov  5 17:43:24 2010
@@ -159,15 +159,15 @@ public class ConcurrentReportingRunListe
         throws TestSetFailedException
     {
         ReporterManagerFactory reporterManagerFactory = 
createReporterFactory();
-        RunStatistics result = runClasses(reporterManagerFactory, new 
ConcurrentReportingRunListener.ClassesParallelRunListener( 
reporterManagerFactory ),  classes);
+        RunStatistics result = runClasses(reporterManagerFactory, new 
ClassesParallelRunListener( reporterManagerFactory ),  classes);
         assertReporter(  result, success, ignored ,failure, "classes" );
 
         reporterManagerFactory = createReporterFactory();
-        result = runClasses(reporterManagerFactory, new 
ConcurrentReportingRunListener.MethodsParallelRunListener(reporterManagerFactory,
 true) , classes);
+        result = runClasses(reporterManagerFactory, new 
MethodsParallelRunListener(reporterManagerFactory, true) , classes);
         assertReporter(  result, success, ignored ,failure, "methods" );
 
         reporterManagerFactory = createReporterFactory();
-        result = runClasses(reporterManagerFactory, new 
ConcurrentReportingRunListener.MethodsParallelRunListener(reporterManagerFactory,
 false) , classes);
+        result = runClasses(reporterManagerFactory, new 
MethodsParallelRunListener(reporterManagerFactory, false) , classes);
         assertReporter(  result, success, ignored ,failure, "methods" );
 
     }
@@ -203,7 +203,7 @@ public class ConcurrentReportingRunListe
     private ConcurrentReportingRunListener createRunListener( 
ReporterManagerFactory reporterFactory )
         throws TestSetFailedException
     {
-        return new ConcurrentReportingRunListener.ClassesParallelRunListener( 
reporterFactory );
+        return new ClassesParallelRunListener( reporterFactory );
     }
 
 

Added: 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java?rev=1031678&view=auto
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java
 (added)
+++ 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java
 Fri Nov  5 17:43:24 2010
@@ -0,0 +1,140 @@
+package org.apache.maven.surefire.testng;
+/*
+ * 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.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.surefire.report.ReporterException;
+import org.apache.maven.surefire.report.ReporterManager;
+
+/**
+ * A proxy that imposes synchronization on the Reporter.
+ * <p/>
+ * <p/>
+ * At the moment this class only provides "compatible" synchronization that 
the testng runner can use,
+ * and provides the same (faulty) level of synchronization as the <2.6 
versions of surefire.
+ * <p/>
+ * In the "future"  when the concurrent junit provider is rid of all problems 
of childhood,
+ * it should probably replace the entire reporting secion for testng too.
+ * <p/>
+ * <p/>
+ * <p/>
+ * This design is really only good for single-threaded test execution. 
Although it is currently
+ * used by testng provider, the design does not really make sense (and is 
buggy).
+ * <p/>
+ * This is because to get correct results, the client basically needs to do 
something like this:
+ * synchronized( ReporterManger.getClass()){
+ * reporterManager.runStarted()
+ * reporterManager.testSetStarting()
+ * reporterManager.testStarting()
+ * reporterManager.testSucceeded()
+ * reporterManager.testSetCompleted()
+ * reporterManager.runCompleted()
+ * }
+ * <p/>
+ * This is because the underlying providers are singletons and keep state, if 
you remove the outer synchronized
+ * block, you may get mixups between results from different tests; although 
the end result (total test count etc)
+ * should probably be correct.
+ * <p/>
+ * <p/>
+ */
+class SynchronizedReporterManager
+    extends ReporterManager
+{
+    public SynchronizedReporterManager( ReporterManager target )
+    {
+        super( target );
+    }
+
+    public synchronized void runStarting()
+    {
+        super.runStarting();
+    }
+
+    public synchronized void runCompleted()
+    {
+        super.runCompleted();
+    }
+
+    public synchronized void testSetStarting( ReportEntry report )
+        throws ReporterException
+    {
+        super.testSetStarting( report );
+    }
+
+    public synchronized void testSetCompleted( ReportEntry report )
+    {
+        super.testSetCompleted( report );
+    }
+
+    public synchronized void testStarting( ReportEntry report )
+    {
+        super.testStarting( report );
+    }
+
+    public synchronized void testSucceeded( ReportEntry report )
+    {
+        super.testSucceeded( report );
+    }
+
+    public synchronized void testError( ReportEntry report, String stdOut, 
String stdErr )
+    {
+        super.testError( report, stdOut, stdErr );
+    }
+
+    public synchronized void testFailed( ReportEntry report, String stdOut, 
String stdErr )
+    {
+        super.testFailed( report, stdOut, stdErr );
+    }
+
+    public synchronized void testSkipped( ReportEntry report )
+    {
+        super.testSkipped( report );
+    }
+
+    public synchronized void reset()
+    {
+        super.reset();
+    }
+
+    public synchronized void writeMessage( String message )
+    {
+        super.writeMessage( message );
+    }
+
+    public synchronized void writeFooter( String footer )
+    {
+        super.writeFooter( footer );
+    }
+
+    public synchronized void writeConsoleMessage( String message )
+    {
+        super.writeConsoleMessage( message );
+    }
+
+    public synchronized void testError( ReportEntry reportEntry )
+    {
+        super.testError( reportEntry );
+    }
+
+    public synchronized void testFailed( ReportEntry reportEntry )
+    {
+        super.testFailed( reportEntry );
+    }
+}

Propchange: 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/SynchronizedReporterManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java?rev=1031678&r1=1031677&r2=1031678&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
 (original)
+++ 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
 Fri Nov  5 17:43:24 2010
@@ -149,7 +149,8 @@ public class TestNGDirectoryTestSuite
             junitReportsDirectory = new File( reportsDirectory, 
"testng-junit-results");
         }
 
-        ReporterManager reporterManager = 
reporterManagerFactory.createReporterManager();
+        ReporterManager reporterManager =
+            new SynchronizedReporterManager( 
reporterManagerFactory.createReporterManager());
         startTestSuite( reporterManager, this );
         
         Class[] testClasses = (Class[]) testNgTestClasses.toArray( new 
Class[0] );

Modified: 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java?rev=1031678&r1=1031677&r2=1031678&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
 (original)
+++ 
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
 Fri Nov  5 17:43:24 2010
@@ -89,7 +89,8 @@ public class TestNGXmlTestSuite
         {
             throw new IllegalStateException( "You must call locateTestSets 
before calling execute" );
         }
-        ReporterManager reporterManager = 
reporterManagerFactory.createReporterManager();
+        ReporterManager reporterManager =
+            new SynchronizedReporterManager( 
reporterManagerFactory.createReporterManager());
         TestNGDirectoryTestSuite.startTestSuite( reporterManager, this );
         TestNGExecutor.run( this.suiteFilePaths, this.testSourceDirectory, 
this.options, this.version, 
                             this.classifier, reporterManager, this, 
reportsDirectory );


Reply via email to