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.extensions.ConsoleOutputReportEventListener;
39  import org.apache.maven.surefire.extensions.StatelessReportEventListener;
40  import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener;
41  import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener;
42  
43  import static java.nio.charset.StandardCharsets.UTF_8;
44  import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
45  import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF;
46  import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN;
47  import static org.apache.maven.surefire.shared.lang3.StringUtils.trimToNull;
48  
49  /**
50   * All the parameters used to construct reporters
51   * <br>
52   *
53   * @author Kristian Rosenvold
54   */
55  public final class StartupReportConfiguration {
56      private final PrintStream originalSystemOut;
57  
58      private final PrintStream originalSystemErr;
59  
60      private final boolean useFile;
61  
62      private final boolean printSummary;
63  
64      private final String reportFormat;
65  
66      private final String reportNameSuffix;
67  
68      private final File statisticsFile;
69  
70      private final boolean requiresRunHistory;
71  
72      private final boolean redirectTestOutputToFile;
73  
74      private final File reportsDirectory;
75  
76      private final boolean trimStackTrace;
77  
78      private final int rerunFailingTestsCount;
79  
80      private final String xsdSchemaLocation;
81  
82      private final Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory = new ConcurrentHashMap<>();
83  
84      private final Charset encoding;
85  
86      private final boolean isForking;
87  
88      private final boolean enableOutErrElements;
89  
90      private final boolean enablePropertiesElement;
91  
92      private final SurefireStatelessReporter xmlReporter;
93  
94      private final SurefireConsoleOutputReporter consoleOutputReporter;
95  
96      private final SurefireStatelessTestsetInfoReporter testsetReporter;
97  
98      private StatisticsReporter statisticsReporter;
99  
100     @SuppressWarnings("checkstyle:parameternumber")
101     public StartupReportConfiguration(
102             boolean useFile,
103             boolean printSummary,
104             String reportFormat,
105             boolean redirectTestOutputToFile,
106             @Nonnull File reportsDirectory,
107             boolean trimStackTrace,
108             String reportNameSuffix,
109             File statisticsFile,
110             boolean requiresRunHistory,
111             int rerunFailingTestsCount,
112             String xsdSchemaLocation,
113             String encoding,
114             boolean isForking,
115             boolean enableOutErrElements,
116             boolean enablePropertiesElement,
117             SurefireStatelessReporter xmlReporter,
118             SurefireConsoleOutputReporter consoleOutputReporter,
119             SurefireStatelessTestsetInfoReporter testsetReporter) {
120         this.useFile = useFile;
121         this.printSummary = printSummary;
122         this.reportFormat = reportFormat;
123         this.redirectTestOutputToFile = redirectTestOutputToFile;
124         this.reportsDirectory = reportsDirectory;
125         this.trimStackTrace = trimStackTrace;
126         this.reportNameSuffix = reportNameSuffix;
127         this.statisticsFile = statisticsFile;
128         this.requiresRunHistory = requiresRunHistory;
129         this.originalSystemOut = System.out;
130         this.originalSystemErr = System.err;
131         this.rerunFailingTestsCount = rerunFailingTestsCount;
132         this.xsdSchemaLocation = xsdSchemaLocation;
133         String charset = trimToNull(encoding);
134         this.encoding = charset == null ? UTF_8 : Charset.forName(charset);
135         this.isForking = isForking;
136         this.enableOutErrElements = enableOutErrElements;
137         this.enablePropertiesElement = enablePropertiesElement;
138         this.xmlReporter = xmlReporter;
139         this.consoleOutputReporter = consoleOutputReporter;
140         this.testsetReporter = testsetReporter;
141     }
142 
143     public boolean isUseFile() {
144         return useFile;
145     }
146 
147     public boolean isPrintSummary() {
148         return printSummary;
149     }
150 
151     public String getReportFormat() {
152         return reportFormat;
153     }
154 
155     public String getReportNameSuffix() {
156         return reportNameSuffix;
157     }
158 
159     public boolean isRedirectTestOutputToFile() {
160         return redirectTestOutputToFile;
161     }
162 
163     public File getReportsDirectory() {
164         return reportsDirectory;
165     }
166 
167     public int getRerunFailingTestsCount() {
168         return rerunFailingTestsCount;
169     }
170 
171     public StatelessReportEventListener<WrappedReportEntry, TestSetStats> instantiateStatelessXmlReporter(
172             Integer forkNumber) {
173         assert (forkNumber == null) == !isForking;
174 
175         // If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful
176         // reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated.
177         // In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and
178         // listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT.
179         Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory =
180                 isForking ? new ConcurrentHashMap<String, Deque<WrappedReportEntry>>() : this.testClassMethodRunHistory;
181 
182         DefaultStatelessReportMojoConfiguration xmlReporterConfig = new DefaultStatelessReportMojoConfiguration(
183                 resolveReportsDirectory(forkNumber),
184                 reportNameSuffix,
185                 trimStackTrace,
186                 rerunFailingTestsCount,
187                 xsdSchemaLocation,
188                 enableOutErrElements,
189                 enablePropertiesElement,
190                 testClassMethodRunHistory);
191 
192         return xmlReporter.isDisable() ? null : xmlReporter.createListener(xmlReporterConfig);
193     }
194 
195     public StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> instantiateFileReporter(
196             Integer forkNumber) {
197         return !testsetReporter.isDisable() && isUseFile() && isBriefOrPlainFormat()
198                 ? testsetReporter.createListener(resolveReportsDirectory(forkNumber), reportNameSuffix, encoding)
199                 : null;
200     }
201 
202     public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> instantiateConsoleReporter(
203             ConsoleLogger consoleLogger) {
204         return !testsetReporter.isDisable() && shouldReportToConsole()
205                 ? testsetReporter.createListener(consoleLogger)
206                 : null;
207     }
208 
209     public boolean isBriefOrPlainFormat() {
210         String fmt = getReportFormat();
211         return BRIEF.equals(fmt) || PLAIN.equals(fmt);
212     }
213 
214     public ConsoleOutputReportEventListener instantiateConsoleOutputFileReporter(Integer forkNum) {
215         ConsoleOutputReportEventListener outputReport = isRedirectTestOutputToFile()
216                 ? consoleOutputReporter.createListener(resolveReportsDirectory(forkNum), reportNameSuffix, forkNum)
217                 : consoleOutputReporter.createListener(originalSystemOut, originalSystemErr);
218         return consoleOutputReporter.isDisable() ? null : outputReport;
219     }
220 
221     public synchronized StatisticsReporter getStatisticsReporter() {
222         if (statisticsReporter == null) {
223             statisticsReporter = requiresRunHistory ? new StatisticsReporter(statisticsFile) : null;
224         }
225         return statisticsReporter;
226     }
227 
228     public File getStatisticsFile() {
229         return statisticsFile;
230     }
231 
232     public boolean isTrimStackTrace() {
233         return trimStackTrace;
234     }
235 
236     public boolean isRequiresRunHistory() {
237         return requiresRunHistory;
238     }
239 
240     public String getXsdSchemaLocation() {
241         return xsdSchemaLocation;
242     }
243 
244     public Charset getEncoding() {
245         return encoding;
246     }
247 
248     public boolean isForking() {
249         return isForking;
250     }
251 
252     public boolean isEnableOutErrElements() {
253         return enableOutErrElements;
254     }
255 
256     public boolean isEnablePropertiesElement() {
257         return enablePropertiesElement;
258     }
259 
260     private File resolveReportsDirectory(Integer forkNumber) {
261         return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath(reportsDirectory, forkNumber);
262     }
263 
264     public SurefireStatelessReporter getXmlReporter() {
265         return xmlReporter;
266     }
267 
268     public SurefireConsoleOutputReporter getConsoleOutputReporter() {
269         return consoleOutputReporter;
270     }
271 
272     public SurefireStatelessTestsetInfoReporter getTestsetReporter() {
273         return testsetReporter;
274     }
275 
276     private boolean shouldReportToConsole() {
277         return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat();
278     }
279 }