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 SurefireStatelessReporter xmlReporter;
89  
90      private final SurefireConsoleOutputReporter consoleOutputReporter;
91  
92      private final SurefireStatelessTestsetInfoReporter testsetReporter;
93  
94      private StatisticsReporter statisticsReporter;
95  
96      @SuppressWarnings("checkstyle:parameternumber")
97      public StartupReportConfiguration(
98              boolean useFile,
99              boolean printSummary,
100             String reportFormat,
101             boolean redirectTestOutputToFile,
102             @Nonnull File reportsDirectory,
103             boolean trimStackTrace,
104             String reportNameSuffix,
105             File statisticsFile,
106             boolean requiresRunHistory,
107             int rerunFailingTestsCount,
108             String xsdSchemaLocation,
109             String encoding,
110             boolean isForking,
111             SurefireStatelessReporter xmlReporter,
112             SurefireConsoleOutputReporter consoleOutputReporter,
113             SurefireStatelessTestsetInfoReporter testsetReporter) {
114         this.useFile = useFile;
115         this.printSummary = printSummary;
116         this.reportFormat = reportFormat;
117         this.redirectTestOutputToFile = redirectTestOutputToFile;
118         this.reportsDirectory = reportsDirectory;
119         this.trimStackTrace = trimStackTrace;
120         this.reportNameSuffix = reportNameSuffix;
121         this.statisticsFile = statisticsFile;
122         this.requiresRunHistory = requiresRunHistory;
123         this.originalSystemOut = System.out;
124         this.originalSystemErr = System.err;
125         this.rerunFailingTestsCount = rerunFailingTestsCount;
126         this.xsdSchemaLocation = xsdSchemaLocation;
127         String charset = trimToNull(encoding);
128         this.encoding = charset == null ? UTF_8 : Charset.forName(charset);
129         this.isForking = isForking;
130         this.xmlReporter = xmlReporter;
131         this.consoleOutputReporter = consoleOutputReporter;
132         this.testsetReporter = testsetReporter;
133     }
134 
135     public boolean isUseFile() {
136         return useFile;
137     }
138 
139     public boolean isPrintSummary() {
140         return printSummary;
141     }
142 
143     public String getReportFormat() {
144         return reportFormat;
145     }
146 
147     public String getReportNameSuffix() {
148         return reportNameSuffix;
149     }
150 
151     public boolean isRedirectTestOutputToFile() {
152         return redirectTestOutputToFile;
153     }
154 
155     public File getReportsDirectory() {
156         return reportsDirectory;
157     }
158 
159     public int getRerunFailingTestsCount() {
160         return rerunFailingTestsCount;
161     }
162 
163     public StatelessReportEventListener<WrappedReportEntry, TestSetStats> instantiateStatelessXmlReporter(
164             Integer forkNumber) {
165         assert (forkNumber == null) == !isForking;
166 
167         // If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful
168         // reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated.
169         // In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and
170         // listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT.
171         Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory =
172                 isForking ? new ConcurrentHashMap<String, Deque<WrappedReportEntry>>() : this.testClassMethodRunHistory;
173 
174         DefaultStatelessReportMojoConfiguration xmlReporterConfig = new DefaultStatelessReportMojoConfiguration(
175                 resolveReportsDirectory(forkNumber),
176                 reportNameSuffix,
177                 trimStackTrace,
178                 rerunFailingTestsCount,
179                 xsdSchemaLocation,
180                 testClassMethodRunHistory);
181 
182         return xmlReporter.isDisable() ? null : xmlReporter.createListener(xmlReporterConfig);
183     }
184 
185     public StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> instantiateFileReporter(
186             Integer forkNumber) {
187         return !testsetReporter.isDisable() && isUseFile() && isBriefOrPlainFormat()
188                 ? testsetReporter.createListener(resolveReportsDirectory(forkNumber), reportNameSuffix, encoding)
189                 : null;
190     }
191 
192     public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> instantiateConsoleReporter(
193             ConsoleLogger consoleLogger) {
194         return !testsetReporter.isDisable() && shouldReportToConsole()
195                 ? testsetReporter.createListener(consoleLogger)
196                 : null;
197     }
198 
199     public boolean isBriefOrPlainFormat() {
200         String fmt = getReportFormat();
201         return BRIEF.equals(fmt) || PLAIN.equals(fmt);
202     }
203 
204     public ConsoleOutputReportEventListener instantiateConsoleOutputFileReporter(Integer forkNum) {
205         ConsoleOutputReportEventListener outputReport = isRedirectTestOutputToFile()
206                 ? consoleOutputReporter.createListener(resolveReportsDirectory(forkNum), reportNameSuffix, forkNum)
207                 : consoleOutputReporter.createListener(originalSystemOut, originalSystemErr);
208         return consoleOutputReporter.isDisable() ? null : outputReport;
209     }
210 
211     public synchronized StatisticsReporter getStatisticsReporter() {
212         if (statisticsReporter == null) {
213             statisticsReporter = requiresRunHistory ? new StatisticsReporter(statisticsFile) : null;
214         }
215         return statisticsReporter;
216     }
217 
218     public File getStatisticsFile() {
219         return statisticsFile;
220     }
221 
222     public boolean isTrimStackTrace() {
223         return trimStackTrace;
224     }
225 
226     public boolean isRequiresRunHistory() {
227         return requiresRunHistory;
228     }
229 
230     public String getXsdSchemaLocation() {
231         return xsdSchemaLocation;
232     }
233 
234     public Charset getEncoding() {
235         return encoding;
236     }
237 
238     public boolean isForking() {
239         return isForking;
240     }
241 
242     private File resolveReportsDirectory(Integer forkNumber) {
243         return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath(reportsDirectory, forkNumber);
244     }
245 
246     public SurefireStatelessReporter getXmlReporter() {
247         return xmlReporter;
248     }
249 
250     public SurefireConsoleOutputReporter getConsoleOutputReporter() {
251         return consoleOutputReporter;
252     }
253 
254     public SurefireStatelessTestsetInfoReporter getTestsetReporter() {
255         return testsetReporter;
256     }
257 
258     private boolean shouldReportToConsole() {
259         return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat();
260     }
261 }