View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.surefire;
20  
21  import javax.annotation.Nonnull;
22  
23  import java.io.File;
24  import java.io.PrintStream;
25  import java.nio.charset.Charset;
26  import java.util.Deque;
27  import java.util.Map;
28  import java.util.concurrent.ConcurrentHashMap;
29  
30  import org.apache.maven.plugin.surefire.extensions.DefaultStatelessReportMojoConfiguration;
31  import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter;
32  import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter;
33  import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter;
34  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
35  import org.apache.maven.plugin.surefire.report.TestSetStats;
36  import org.apache.maven.plugin.surefire.report.WrappedReportEntry;
37  import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
38  import org.apache.maven.surefire.api.report.ReporterFactoryOptions;
39  import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener;
40  import org.apache.maven.surefire.extensions.StatelessReportEventListener;
41  import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener;
42  import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener;
43  
44  import static java.nio.charset.StandardCharsets.UTF_8;
45  import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
46  import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF;
47  import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN;
48  import static org.apache.maven.surefire.shared.lang3.StringUtils.trimToNull;
49  
50  /**
51   * All the parameters used to construct reporters
52   * <br>
53   *
54   * @author Kristian Rosenvold
55   */
56  public final class StartupReportConfiguration {
57      private final PrintStream originalSystemOut;
58  
59      private final PrintStream originalSystemErr;
60  
61      private final boolean useFile;
62  
63      private final boolean printSummary;
64  
65      private final String reportFormat;
66  
67      private final String reportNameSuffix;
68  
69      private final File statisticsFile;
70  
71      private final boolean requiresRunHistory;
72  
73      private final boolean redirectTestOutputToFile;
74  
75      private final File reportsDirectory;
76  
77      private final boolean trimStackTrace;
78  
79      private final int rerunFailingTestsCount;
80  
81      private final String xsdSchemaLocation;
82  
83      private final Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory = new ConcurrentHashMap<>();
84  
85      private final Charset encoding;
86  
87      private final boolean isForking;
88  
89      private final boolean enableOutErrElements;
90  
91      private final boolean enablePropertiesElement;
92  
93      private final SurefireStatelessReporter xmlReporter;
94  
95      private final SurefireConsoleOutputReporter consoleOutputReporter;
96  
97      private final SurefireStatelessTestsetInfoReporter testsetReporter;
98  
99      private StatisticsReporter statisticsReporter;
100 
101     private final ReporterFactoryOptions reporterFactoryOptions;
102 
103     /**
104      * @since 3.3.1
105      */
106     @SuppressWarnings("checkstyle:parameternumber")
107     public StartupReportConfiguration(
108             boolean useFile,
109             boolean printSummary,
110             String reportFormat,
111             boolean redirectTestOutputToFile,
112             @Nonnull File reportsDirectory,
113             boolean trimStackTrace,
114             String reportNameSuffix,
115             File statisticsFile,
116             boolean requiresRunHistory,
117             int rerunFailingTestsCount,
118             String xsdSchemaLocation,
119             String encoding,
120             boolean isForking,
121             boolean enableOutErrElements,
122             boolean enablePropertiesElement,
123             SurefireStatelessReporter xmlReporter,
124             SurefireConsoleOutputReporter consoleOutputReporter,
125             SurefireStatelessTestsetInfoReporter testsetReporter,
126             ReporterFactoryOptions reporterFactoryOptions) {
127         this.useFile = useFile;
128         this.printSummary = printSummary;
129         this.reportFormat = reportFormat;
130         this.redirectTestOutputToFile = redirectTestOutputToFile;
131         this.reportsDirectory = reportsDirectory;
132         this.trimStackTrace = trimStackTrace;
133         this.reportNameSuffix = reportNameSuffix;
134         this.statisticsFile = statisticsFile;
135         this.requiresRunHistory = requiresRunHistory;
136         this.originalSystemOut = System.out;
137         this.originalSystemErr = System.err;
138         this.rerunFailingTestsCount = rerunFailingTestsCount;
139         this.xsdSchemaLocation = xsdSchemaLocation;
140         String charset = trimToNull(encoding);
141         this.encoding = charset == null ? UTF_8 : Charset.forName(charset);
142         this.isForking = isForking;
143         this.enableOutErrElements = enableOutErrElements;
144         this.enablePropertiesElement = enablePropertiesElement;
145         this.xmlReporter = xmlReporter;
146         this.consoleOutputReporter = consoleOutputReporter;
147         this.testsetReporter = testsetReporter;
148         this.reporterFactoryOptions = reporterFactoryOptions;
149     }
150 
151     @SuppressWarnings("checkstyle:parameternumber")
152     @Deprecated
153     public StartupReportConfiguration(
154             boolean useFile,
155             boolean printSummary,
156             String reportFormat,
157             boolean redirectTestOutputToFile,
158             @Nonnull File reportsDirectory,
159             boolean trimStackTrace,
160             String reportNameSuffix,
161             File statisticsFile,
162             boolean requiresRunHistory,
163             int rerunFailingTestsCount,
164             String xsdSchemaLocation,
165             String encoding,
166             boolean isForking,
167             SurefireStatelessReporter xmlReporter,
168             SurefireConsoleOutputReporter consoleOutputReporter,
169             SurefireStatelessTestsetInfoReporter testsetReporter) {
170         this(
171                 useFile,
172                 printSummary,
173                 reportFormat,
174                 redirectTestOutputToFile,
175                 reportsDirectory,
176                 trimStackTrace,
177                 reportNameSuffix,
178                 statisticsFile,
179                 requiresRunHistory,
180                 rerunFailingTestsCount,
181                 xsdSchemaLocation,
182                 encoding,
183                 isForking,
184                 true,
185                 true,
186                 xmlReporter,
187                 consoleOutputReporter,
188                 testsetReporter,
189                 new ReporterFactoryOptions(false));
190     }
191 
192     public boolean isUseFile() {
193         return useFile;
194     }
195 
196     public boolean isPrintSummary() {
197         return printSummary;
198     }
199 
200     public String getReportFormat() {
201         return reportFormat;
202     }
203 
204     public String getReportNameSuffix() {
205         return reportNameSuffix;
206     }
207 
208     public boolean isRedirectTestOutputToFile() {
209         return redirectTestOutputToFile;
210     }
211 
212     public File getReportsDirectory() {
213         return reportsDirectory;
214     }
215 
216     public int getRerunFailingTestsCount() {
217         return rerunFailingTestsCount;
218     }
219 
220     public StatelessReportEventListener<WrappedReportEntry, TestSetStats> instantiateStatelessXmlReporter(
221             Integer forkNumber) {
222         assert (forkNumber == null) == !isForking;
223 
224         // If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful
225         // reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated.
226         // In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and
227         // listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT.
228         Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory =
229                 isForking ? new ConcurrentHashMap<>() : this.testClassMethodRunHistory;
230 
231         DefaultStatelessReportMojoConfiguration xmlReporterConfig = new DefaultStatelessReportMojoConfiguration(
232                 resolveReportsDirectory(forkNumber),
233                 reportNameSuffix,
234                 trimStackTrace,
235                 rerunFailingTestsCount,
236                 xsdSchemaLocation,
237                 enableOutErrElements,
238                 enablePropertiesElement,
239                 testClassMethodRunHistory);
240 
241         return xmlReporter.isDisable() ? null : xmlReporter.createListener(xmlReporterConfig);
242     }
243 
244     public StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> instantiateFileReporter(
245             Integer forkNumber) {
246         return !testsetReporter.isDisable() && isUseFile() && isBriefOrPlainFormat()
247                 ? testsetReporter.createListener(resolveReportsDirectory(forkNumber), reportNameSuffix, encoding)
248                 : null;
249     }
250 
251     public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> instantiateConsoleReporter(
252             ConsoleLogger consoleLogger) {
253         return !testsetReporter.isDisable() && shouldReportToConsole()
254                 ? testsetReporter.createListener(consoleLogger)
255                 : null;
256     }
257 
258     public boolean isBriefOrPlainFormat() {
259         String fmt = getReportFormat();
260         return BRIEF.equals(fmt) || PLAIN.equals(fmt);
261     }
262 
263     public ConsoleOutputReportEventListener instantiateConsoleOutputFileReporter(Integer forkNum) {
264         ConsoleOutputReportEventListener outputReport = isRedirectTestOutputToFile()
265                 ? consoleOutputReporter.createListener(resolveReportsDirectory(forkNum), reportNameSuffix, forkNum)
266                 : consoleOutputReporter.createListener(originalSystemOut, originalSystemErr);
267         return consoleOutputReporter.isDisable() ? null : outputReport;
268     }
269 
270     public synchronized StatisticsReporter getStatisticsReporter() {
271         if (statisticsReporter == null) {
272             statisticsReporter = requiresRunHistory ? new StatisticsReporter(statisticsFile) : null;
273         }
274         return statisticsReporter;
275     }
276 
277     public File getStatisticsFile() {
278         return statisticsFile;
279     }
280 
281     public boolean isTrimStackTrace() {
282         return trimStackTrace;
283     }
284 
285     public boolean isRequiresRunHistory() {
286         return requiresRunHistory;
287     }
288 
289     public String getXsdSchemaLocation() {
290         return xsdSchemaLocation;
291     }
292 
293     public Charset getEncoding() {
294         return encoding;
295     }
296 
297     public boolean isForking() {
298         return isForking;
299     }
300 
301     public boolean isEnableOutErrElements() {
302         return enableOutErrElements;
303     }
304 
305     public boolean isEnablePropertiesElement() {
306         return enablePropertiesElement;
307     }
308 
309     private File resolveReportsDirectory(Integer forkNumber) {
310         return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath(reportsDirectory, forkNumber);
311     }
312 
313     public SurefireStatelessReporter getXmlReporter() {
314         return xmlReporter;
315     }
316 
317     public SurefireConsoleOutputReporter getConsoleOutputReporter() {
318         return consoleOutputReporter;
319     }
320 
321     public SurefireStatelessTestsetInfoReporter getTestsetReporter() {
322         return testsetReporter;
323     }
324 
325     private boolean shouldReportToConsole() {
326         return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat();
327     }
328 
329     public ReporterFactoryOptions getReporterFactoryOptions() {
330         return reporterFactoryOptions;
331     }
332 }