View Javadoc
1   package org.apache.maven.surefire.junitcore;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Set;
26  import java.util.concurrent.ConcurrentHashMap;
27  
28  import org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil;
29  import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
30  import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
31  import org.apache.maven.surefire.common.junit48.FilterFactory;
32  import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
33  import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
34  import org.apache.maven.surefire.providerapi.AbstractProvider;
35  import org.apache.maven.surefire.providerapi.ProviderParameters;
36  import org.apache.maven.surefire.report.ConsoleLogger;
37  import org.apache.maven.surefire.report.ConsoleOutputCapture;
38  import org.apache.maven.surefire.report.ConsoleOutputReceiver;
39  import org.apache.maven.surefire.report.ReporterFactory;
40  import org.apache.maven.surefire.report.RunListener;
41  import org.apache.maven.surefire.suite.RunResult;
42  import org.apache.maven.surefire.testset.TestSetFailedException;
43  import org.apache.maven.surefire.util.RunOrderCalculator;
44  import org.apache.maven.surefire.util.ScanResult;
45  import org.apache.maven.surefire.util.ScannerFilter;
46  import org.apache.maven.surefire.util.TestsToRun;
47  import org.apache.maven.surefire.util.internal.StringUtils;
48  import org.junit.runner.manipulation.Filter;
49  
50  /**
51   * @author Kristian Rosenvold
52   */
53  @SuppressWarnings( { "UnusedDeclaration" } )
54  public class JUnitCoreProvider
55      extends AbstractProvider
56  {
57      private final ClassLoader testClassLoader;
58  
59      private final JUnitCoreParameters jUnitCoreParameters;
60  
61      private final ScannerFilter scannerFilter;
62  
63      private final List<org.junit.runner.notification.RunListener> customRunListeners;
64  
65      private final ProviderParameters providerParameters;
66  
67      private final ScanResult scanResult;
68  
69      private final int rerunFailingTestsCount;
70  
71      private TestsToRun testsToRun;
72  
73      private JUnit48Reflector jUnit48Reflector;
74  
75      private RunOrderCalculator runOrderCalculator;
76  
77      private String requestedTestMethod;
78  
79      public JUnitCoreProvider( ProviderParameters providerParameters )
80      {
81          this.providerParameters = providerParameters;
82          testClassLoader = providerParameters.getTestClassLoader();
83          scanResult = providerParameters.getScanResult();
84          runOrderCalculator = providerParameters.getRunOrderCalculator();
85          jUnitCoreParameters = new JUnitCoreParameters( providerParameters.getProviderProperties() );
86          scannerFilter = new JUnit48TestChecker( testClassLoader );
87          requestedTestMethod = providerParameters.getTestRequest().getRequestedTestMethod();
88          rerunFailingTestsCount = providerParameters.getTestRequest().getRerunFailingTestsCount();
89  
90          customRunListeners =
91              JUnit4RunListenerFactory.createCustomListeners(
92                  providerParameters.getProviderProperties().getProperty( "listener" ) );
93          jUnit48Reflector = new JUnit48Reflector( testClassLoader );
94      }
95  
96      public Boolean isRunnable()
97      {
98          return Boolean.TRUE;
99      }
100 
101     public Iterator getSuites()
102     {
103         testsToRun = scanClassPath();
104         return testsToRun.iterator();
105     }
106 
107     private boolean isSingleThreaded()
108     {
109         return jUnitCoreParameters.isNoThreading();
110     }
111 
112     public RunResult invoke( Object forkTestSet )
113         throws TestSetFailedException
114     {
115         final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
116 
117         final ConsoleLogger consoleLogger = providerParameters.getConsoleLogger();
118 
119         Filter filter = jUnit48Reflector.isJUnit48Available() ? createJUnit48Filter() : null;
120 
121         if ( testsToRun == null )
122         {
123             if ( forkTestSet instanceof TestsToRun )
124             {
125                 testsToRun = (TestsToRun) forkTestSet;
126             }
127             else if ( forkTestSet instanceof Class )
128             {
129                 Class theClass = (Class) forkTestSet;
130                 testsToRun = TestsToRun.fromClass( theClass );
131             }
132             else
133             {
134                 testsToRun = scanClassPath();
135             }
136         }
137 
138         customRunListeners.add( 0, getRunListener( reporterFactory, consoleLogger ) );
139 
140         // Add test failure listener
141         JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
142         customRunListeners.add( 0, testFailureListener );
143 
144         JUnitCoreWrapper.execute( consoleLogger, testsToRun, jUnitCoreParameters, customRunListeners, filter );
145 
146         // Rerun failing tests if rerunFailingTestsCount is larger than 0
147         if ( rerunFailingTestsCount > 0 )
148         {
149             for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
150             {
151                 Map<Class<?>, Set<String>> failingTests =
152                     JUnit4ProviderUtil.generateFailingTests( testFailureListener.getAllFailures(), testsToRun );
153                 testFailureListener.reset();
154                 final FilterFactory filterFactory = new FilterFactory( testClassLoader );
155                 Filter failingMethodsFilter = filterFactory.createFailingMethodFilter( failingTests );
156                 JUnitCoreWrapper.execute( consoleLogger, testsToRun, jUnitCoreParameters, customRunListeners,
157                                           filterFactory.and( filter, failingMethodsFilter ) );
158             }
159         }
160         return reporterFactory.close();
161     }
162 
163     private org.junit.runner.notification.RunListener getRunListener( ReporterFactory reporterFactory,
164                                                                       ConsoleLogger consoleLogger )
165         throws TestSetFailedException
166     {
167         org.junit.runner.notification.RunListener jUnit4RunListener;
168         if ( isSingleThreaded() )
169         {
170             NonConcurrentRunListener rm = new NonConcurrentRunListener( reporterFactory.createReporter() );
171             ConsoleOutputCapture.startCapture( rm );
172             jUnit4RunListener = rm;
173         }
174         else
175         {
176             final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
177 
178             RunListener listener =
179                 ConcurrentRunListener.createInstance( testSetMap, reporterFactory,
180                                                       isParallelTypes(),
181                                                       isParallelMethodsAndTypes(), consoleLogger );
182             ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) listener );
183 
184             jUnit4RunListener = new JUnitCoreRunListener( listener, testSetMap );
185         }
186         return jUnit4RunListener;
187     }
188 
189     private boolean isParallelMethodsAndTypes()
190     {
191         return jUnitCoreParameters.isParallelMethods() && isParallelTypes();
192     }
193 
194     private boolean isParallelTypes()
195     {
196         return jUnitCoreParameters.isParallelClasses() || jUnitCoreParameters.isParallelSuites();
197     }
198 
199     private Filter createJUnit48Filter()
200     {
201         final FilterFactory filterFactory = new FilterFactory( testClassLoader );
202         Filter groupFilter = filterFactory.createGroupFilter( providerParameters.getProviderProperties() );
203         return isMethodFilterSpecified() ? filterFactory.and( groupFilter,
204                                                               filterFactory.createMethodFilter( requestedTestMethod ) )
205                         : groupFilter;
206     }
207 
208     private TestsToRun scanClassPath()
209     {
210         final TestsToRun scanned = scanResult.applyFilter( scannerFilter, testClassLoader );
211         return runOrderCalculator.orderTestClasses( scanned );
212     }
213 
214     private boolean isMethodFilterSpecified()
215     {
216         return !StringUtils.isBlank( requestedTestMethod );
217     }
218 }