View Javadoc
1   package org.apache.maven.surefire.testng;
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 org.apache.maven.surefire.api.booter.Command;
23  import org.apache.maven.surefire.api.provider.CommandChainReader;
24  import org.apache.maven.surefire.api.provider.CommandListener;
25  import org.apache.maven.surefire.api.cli.CommandLineOption;
26  import org.apache.maven.surefire.api.provider.AbstractProvider;
27  import org.apache.maven.surefire.api.provider.ProviderParameters;
28  import org.apache.maven.surefire.api.report.ConsoleOutputReceiver;
29  import org.apache.maven.surefire.api.report.ReporterConfiguration;
30  import org.apache.maven.surefire.api.report.ReporterFactory;
31  import org.apache.maven.surefire.api.report.RunListener;
32  import org.apache.maven.surefire.api.suite.RunResult;
33  import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
34  import org.apache.maven.surefire.api.testset.TestListResolver;
35  import org.apache.maven.surefire.api.testset.TestRequest;
36  import org.apache.maven.surefire.api.testset.TestSetFailedException;
37  import org.apache.maven.surefire.api.util.RunOrderCalculator;
38  import org.apache.maven.surefire.api.util.ScanResult;
39  import org.apache.maven.surefire.api.util.TestsToRun;
40  
41  import java.io.File;
42  import java.util.Collection;
43  import java.util.List;
44  import java.util.Map;
45  
46  import static org.apache.maven.surefire.api.report.ConsoleOutputCapture.startCapture;
47  import static org.apache.maven.surefire.api.testset.TestListResolver.getEmptyTestListResolver;
48  import static org.apache.maven.surefire.api.testset.TestListResolver.optionallyWildcardFilter;
49  import static org.apache.maven.surefire.api.util.TestsToRun.fromClass;
50  
51  /**
52   * @author Kristian Rosenvold
53   */
54  public class TestNGProvider
55      extends AbstractProvider
56  {
57      private final Map<String, String> providerProperties;
58  
59      private final ReporterConfiguration reporterConfiguration;
60  
61      private final ClassLoader testClassLoader;
62  
63      private final ScanResult scanResult;
64  
65      private final TestRequest testRequest;
66  
67      private final ProviderParameters providerParameters;
68  
69      private final RunOrderCalculator runOrderCalculator;
70  
71      private final List<CommandLineOption> mainCliOptions;
72  
73      private final CommandChainReader commandsReader;
74  
75      private TestsToRun testsToRun;
76  
77      public TestNGProvider( ProviderParameters bootParams )
78      {
79          // don't start a thread in CommandReader while we are in in-plugin process
80          commandsReader = bootParams.isInsideFork() ? bootParams.getCommandReader() : null;
81          providerParameters = bootParams;
82          testClassLoader = bootParams.getTestClassLoader();
83          runOrderCalculator = bootParams.getRunOrderCalculator();
84          providerProperties = bootParams.getProviderProperties();
85          testRequest = bootParams.getTestRequest();
86          reporterConfiguration = bootParams.getReporterConfiguration();
87          scanResult = bootParams.getScanResult();
88          mainCliOptions = bootParams.getMainCliOptions();
89      }
90  
91      @Override
92      public RunResult invoke( Object forkTestSet )
93          throws TestSetFailedException
94      {
95          if ( isFailFast() && commandsReader != null )
96          {
97              registerPleaseStopListener();
98          }
99  
100         final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
101         final RunListener reporter = reporterFactory.createReporter();
102         /*
103          * {@link org.apache.maven.surefire.api.report.ConsoleOutputCapture#startCapture(ConsoleOutputReceiver)}
104          * called in prior to initializing variable {@link #testsToRun}
105          */
106         startCapture( (ConsoleOutputReceiver) reporter );
107 
108         RunResult runResult;
109         try
110         {
111             if ( isTestNGXmlTestSuite( testRequest ) )
112             {
113                 if ( commandsReader != null )
114                 {
115                     commandsReader.awaitStarted();
116                 }
117                 TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite();
118                 testNGXmlTestSuite.locateTestSets();
119                 testNGXmlTestSuite.execute( reporter );
120             }
121             else
122             {
123                 if ( testsToRun == null )
124                 {
125                     if ( forkTestSet instanceof TestsToRun )
126                     {
127                         testsToRun = (TestsToRun) forkTestSet;
128                     }
129                     else if ( forkTestSet instanceof Class )
130                     {
131                         testsToRun = fromClass( (Class<?>) forkTestSet );
132                     }
133                     else
134                     {
135                         testsToRun = scanClassPath();
136                     }
137                 }
138 
139                 if ( commandsReader != null )
140                 {
141                     registerShutdownListener( testsToRun );
142                     commandsReader.awaitStarted();
143                 }
144                 TestNGDirectoryTestSuite suite = newDirectorySuite();
145                 suite.execute( testsToRun, reporter );
146             }
147         }
148         finally
149         {
150             runResult = reporterFactory.close();
151         }
152         return runResult;
153     }
154 
155     boolean isTestNGXmlTestSuite( TestRequest testSuiteDefinition )
156     {
157         Collection<File> suiteXmlFiles = testSuiteDefinition.getSuiteXmlFiles();
158         return !suiteXmlFiles.isEmpty() && !hasSpecificTests();
159     }
160 
161     private boolean isFailFast()
162     {
163         return providerParameters.getSkipAfterFailureCount() > 0;
164     }
165 
166     private int getSkipAfterFailureCount()
167     {
168         return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0;
169     }
170 
171     private void registerShutdownListener( final TestsToRun testsToRun )
172     {
173         commandsReader.addShutdownListener( new CommandListener()
174         {
175             @Override
176             public void update( Command command )
177             {
178                 testsToRun.markTestSetFinished();
179             }
180         } );
181     }
182 
183     private void registerPleaseStopListener()
184     {
185         commandsReader.addSkipNextTestsListener( new CommandListener()
186         {
187             @Override
188             public void update( Command command )
189             {
190                 FailFastEventsSingleton.getInstance().setSkipOnNextTest();
191             }
192         } );
193     }
194 
195     private TestNGDirectoryTestSuite newDirectorySuite()
196     {
197         return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
198                                              reporterConfiguration.getReportsDirectory(), getTestFilter(),
199                                              mainCliOptions, getSkipAfterFailureCount() );
200     }
201 
202     private TestNGXmlTestSuite newXmlSuite()
203     {
204         return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(),
205                                        testRequest.getTestSourceDirectory().toString(),
206                                        providerProperties,
207                                        reporterConfiguration.getReportsDirectory(), getSkipAfterFailureCount() );
208     }
209 
210     @Override
211     @SuppressWarnings( "unchecked" )
212     public Iterable<Class<?>> getSuites()
213     {
214         if ( isTestNGXmlTestSuite( testRequest ) )
215         {
216             try
217             {
218                 return newXmlSuite().locateTestSets();
219             }
220             catch ( TestSetFailedException e )
221             {
222                 throw new RuntimeException( e );
223             }
224         }
225         else
226         {
227             testsToRun = scanClassPath();
228             return testsToRun;
229         }
230     }
231 
232     private TestsToRun scanClassPath()
233     {
234         final TestsToRun scanned = scanResult.applyFilter( null, testClassLoader );
235         return runOrderCalculator.orderTestClasses( scanned );
236     }
237 
238     private boolean hasSpecificTests()
239     {
240         TestListResolver specificTestPatterns = testRequest.getTestListResolver();
241         return !specificTestPatterns.isEmpty() && !specificTestPatterns.isWildcard();
242     }
243 
244     private TestListResolver getTestFilter()
245     {
246         TestListResolver filter = optionallyWildcardFilter( testRequest.getTestListResolver() );
247         return filter.isWildcard() ? getEmptyTestListResolver() : filter;
248     }
249 }