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 boolean reportTestTimestamp;
94  
95      private final SurefireStatelessReporter xmlReporter;
96  
97      private final SurefireConsoleOutputReporter consoleOutputReporter;
98  
99      private final SurefireStatelessTestsetInfoReporter testsetReporter;
100 
101     private StatisticsReporter statisticsReporter;
102 
103     private final ReporterFactoryOptions reporterFactoryOptions;
104 
105     /**
106      * @since 3.3.1
107      */
108     @SuppressWarnings("checkstyle:parameternumber")
109     public StartupReportConfiguration(
110             boolean useFile,
111             boolean printSummary,
112             String reportFormat,
113             boolean redirectTestOutputToFile,
114             @Nonnull File reportsDirectory,
115             boolean trimStackTrace,
116             String reportNameSuffix,
117             File statisticsFile,
118             boolean requiresRunHistory,
119             int rerunFailingTestsCount,
120             String xsdSchemaLocation,
121             String encoding,
122             boolean isForking,
123             boolean enableOutErrElements,
124             boolean enablePropertiesElement,
125             boolean reportTestTimestamp,
126             SurefireStatelessReporter xmlReporter,
127             SurefireConsoleOutputReporter consoleOutputReporter,
128             SurefireStatelessTestsetInfoReporter testsetReporter,
129             ReporterFactoryOptions reporterFactoryOptions) {
130         this.useFile = useFile;
131         this.printSummary = printSummary;
132         this.reportFormat = reportFormat;
133         this.redirectTestOutputToFile = redirectTestOutputToFile;
134         this.reportsDirectory = reportsDirectory;
135         this.trimStackTrace = trimStackTrace;
136         this.reportNameSuffix = reportNameSuffix;
137         this.statisticsFile = statisticsFile;
138         this.requiresRunHistory = requiresRunHistory;
139         this.originalSystemOut = System.out;
140         this.originalSystemErr = System.err;
141         this.rerunFailingTestsCount = rerunFailingTestsCount;
142         this.xsdSchemaLocation = xsdSchemaLocation;
143         String charset = trimToNull(encoding);
144         this.encoding = charset == null ? UTF_8 : Charset.forName(charset);
145         this.isForking = isForking;
146         this.enableOutErrElements = enableOutErrElements;
147         this.enablePropertiesElement = enablePropertiesElement;
148         this.reportTestTimestamp = reportTestTimestamp;
149         this.xmlReporter = xmlReporter;
150         this.consoleOutputReporter = consoleOutputReporter;
151         this.testsetReporter = testsetReporter;
152         this.reporterFactoryOptions = reporterFactoryOptions;
153     }
154 
155     @SuppressWarnings("checkstyle:parameternumber")
156     @Deprecated
157     public StartupReportConfiguration(
158             boolean useFile,
159             boolean printSummary,
160             String reportFormat,
161             boolean redirectTestOutputToFile,
162             @Nonnull File reportsDirectory,
163             boolean trimStackTrace,
164             String reportNameSuffix,
165             File statisticsFile,
166             boolean requiresRunHistory,
167             int rerunFailingTestsCount,
168             String xsdSchemaLocation,
169             String encoding,
170             boolean isForking,
171             SurefireStatelessReporter xmlReporter,
172             SurefireConsoleOutputReporter consoleOutputReporter,
173             SurefireStatelessTestsetInfoReporter testsetReporter) {
174         this(
175                 useFile,
176                 printSummary,
177                 reportFormat,
178                 redirectTestOutputToFile,
179                 reportsDirectory,
180                 trimStackTrace,
181                 reportNameSuffix,
182                 statisticsFile,
183                 requiresRunHistory,
184                 rerunFailingTestsCount,
185                 xsdSchemaLocation,
186                 encoding,
187                 isForking,
188                 true,
189                 true,
190                 false,
191                 xmlReporter,
192                 consoleOutputReporter,
193                 testsetReporter,
194                 new ReporterFactoryOptions(false));
195     }
196 
197     public boolean isUseFile() {
198         return useFile;
199     }
200 
201     public boolean isPrintSummary() {
202         return printSummary;
203     }
204 
205     public String getReportFormat() {
206         return reportFormat;
207     }
208 
209     public String getReportNameSuffix() {
210         return reportNameSuffix;
211     }
212 
213     public boolean isRedirectTestOutputToFile() {
214         return redirectTestOutputToFile;
215     }
216 
217     public File getReportsDirectory() {
218         return reportsDirectory;
219     }
220 
221     public int getRerunFailingTestsCount() {
222         return rerunFailingTestsCount;
223     }
224 
225     public StatelessReportEventListener<WrappedReportEntry, TestSetStats> instantiateStatelessXmlReporter(
226             Integer forkNumber) {
227         assert (forkNumber == null) == !isForking;
228 
229         // If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful
230         // reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated.
231         // In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and
232         // listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT.
233         Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory =
234                 isForking ? new ConcurrentHashMap<>() : this.testClassMethodRunHistory;
235 
236         DefaultStatelessReportMojoConfiguration xmlReporterConfig = new DefaultStatelessReportMojoConfiguration(
237                 resolveReportsDirectory(forkNumber),
238                 reportNameSuffix,
239                 trimStackTrace,
240                 rerunFailingTestsCount,
241                 xsdSchemaLocation,
242                 enableOutErrElements,
243                 enablePropertiesElement,
244                 reportTestTimestamp,
245                 testClassMethodRunHistory);
246 
247         return xmlReporter.isDisable() ? null : xmlReporter.createListener(xmlReporterConfig);
248     }
249 
250     public StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> instantiateFileReporter(
251             Integer forkNumber) {
252         return !testsetReporter.isDisable() && isUseFile() && isBriefOrPlainFormat()
253                 ? testsetReporter.createListener(resolveReportsDirectory(forkNumber), reportNameSuffix, encoding)
254                 : null;
255     }
256 
257     public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> instantiateConsoleReporter(
258             ConsoleLogger consoleLogger) {
259         return !testsetReporter.isDisable() && shouldReportToConsole()
260                 ? testsetReporter.createListener(consoleLogger)
261                 : null;
262     }
263 
264     public boolean isBriefOrPlainFormat() {
265         String fmt = getReportFormat();
266         return BRIEF.equals(fmt) || PLAIN.equals(fmt);
267     }
268 
269     public ConsoleOutputReportEventListener instantiateConsoleOutputFileReporter(Integer forkNum) {
270         ConsoleOutputReportEventListener outputReport = isRedirectTestOutputToFile()
271                 ? consoleOutputReporter.createListener(resolveReportsDirectory(forkNum), reportNameSuffix, forkNum)
272                 : consoleOutputReporter.createListener(originalSystemOut, originalSystemErr);
273         return consoleOutputReporter.isDisable() ? null : outputReport;
274     }
275 
276     public synchronized StatisticsReporter getStatisticsReporter() {
277         if (statisticsReporter == null) {
278             statisticsReporter = requiresRunHistory ? new StatisticsReporter(statisticsFile) : null;
279         }
280         return statisticsReporter;
281     }
282 
283     public File getStatisticsFile() {
284         return statisticsFile;
285     }
286 
287     public boolean isTrimStackTrace() {
288         return trimStackTrace;
289     }
290 
291     public boolean isRequiresRunHistory() {
292         return requiresRunHistory;
293     }
294 
295     public String getXsdSchemaLocation() {
296         return xsdSchemaLocation;
297     }
298 
299     public Charset getEncoding() {
300         return encoding;
301     }
302 
303     public boolean isForking() {
304         return isForking;
305     }
306 
307     public boolean isEnableOutErrElements() {
308         return enableOutErrElements;
309     }
310 
311     public boolean isEnablePropertiesElement() {
312         return enablePropertiesElement;
313     }
314 
315     public boolean isReportTestTimestamp() {
316         return reportTestTimestamp;
317     }
318 
319     private File resolveReportsDirectory(Integer forkNumber) {
320         return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath(reportsDirectory, forkNumber);
321     }
322 
323     public SurefireStatelessReporter getXmlReporter() {
324         return xmlReporter;
325     }
326 
327     public SurefireConsoleOutputReporter getConsoleOutputReporter() {
328         return consoleOutputReporter;
329     }
330 
331     public SurefireStatelessTestsetInfoReporter getTestsetReporter() {
332         return testsetReporter;
333     }
334 
335     private boolean shouldReportToConsole() {
336         return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat();
337     }
338 
339     public ReporterFactoryOptions getReporterFactoryOptions() {
340         return reporterFactoryOptions;
341     }
342 }