1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugin.failsafe;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.Collection;
24  
25  import org.apache.maven.execution.MavenSession;
26  import org.apache.maven.plugin.AbstractMojo;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.apache.maven.plugin.failsafe.util.FailsafeSummaryXmlUtils;
30  import org.apache.maven.plugin.surefire.SurefireHelper;
31  import org.apache.maven.plugin.surefire.SurefireReportParameters;
32  import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
33  import org.apache.maven.plugins.annotations.LifecyclePhase;
34  import org.apache.maven.plugins.annotations.Mojo;
35  import org.apache.maven.plugins.annotations.Parameter;
36  import org.apache.maven.surefire.api.cli.CommandLineOption;
37  import org.apache.maven.surefire.api.suite.RunResult;
38  import org.apache.maven.surefire.booter.SurefireBooterForkException;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution;
43  import static org.apache.maven.surefire.api.suite.RunResult.noTestsRun;
44  import static org.apache.maven.surefire.shared.utils.StringUtils.capitalizeFirstLetter;
45  
46  
47  
48  
49  
50  
51  
52  @SuppressWarnings("unused")
53  @Mojo(name = "verify", defaultPhase = LifecyclePhase.VERIFY, requiresProject = true, threadSafe = true)
54  public class VerifyMojo extends AbstractMojo implements SurefireReportParameters {
55  
56      
57  
58  
59  
60  
61  
62      @Parameter(property = "skipTests")
63      private boolean skipTests;
64  
65      
66  
67  
68  
69  
70  
71      @Parameter(property = "skipITs")
72      private boolean skipITs;
73  
74      
75  
76  
77  
78  
79  
80      @Deprecated
81      @Parameter(property = "maven.test.skip.exec")
82      private boolean skipExec;
83  
84      
85  
86  
87  
88  
89      @Parameter(property = "maven.test.skip", defaultValue = "false")
90      private boolean skip;
91  
92      
93  
94  
95  
96      @Parameter(property = "maven.test.failure.ignore", defaultValue = "false")
97      private boolean testFailureIgnore;
98  
99      
100 
101 
102 
103     @Parameter(defaultValue = "${basedir}")
104     private File basedir;
105 
106     
107 
108 
109 
110     @Parameter(defaultValue = "${project.build.testOutputDirectory}")
111     private File testClassesDirectory;
112 
113     
114 
115 
116     @Parameter(defaultValue = "${project.build.directory}/failsafe-reports")
117     private File reportsDirectory;
118 
119     
120 
121 
122     @Parameter(defaultValue = "${project.build.directory}/failsafe-reports/failsafe-summary.xml", required = true)
123     private File summaryFile;
124 
125     
126 
127 
128 
129     @Parameter
130     private File[] summaryFiles;
131 
132     
133 
134 
135 
136 
137     @Parameter(property = "failIfNoTests", defaultValue = "false")
138     private boolean failIfNoTests;
139 
140     
141 
142 
143 
144 
145 
146     @Parameter(property = "failsafe.failOnFlakeCount", defaultValue = "0")
147     private int failOnFlakeCount;
148 
149     
150 
151 
152 
153 
154     @Deprecated
155     @Parameter(property = "encoding", defaultValue = "${project.reporting.outputEncoding}")
156     private String encoding;
157 
158     
159 
160 
161     @Parameter(defaultValue = "${session}", readonly = true)
162     private MavenSession session;
163 
164     private final Logger logger;
165 
166     private Collection<CommandLineOption> cli;
167 
168     private volatile PluginConsoleLogger consoleLogger;
169 
170     public VerifyMojo() {
171         this.logger = LoggerFactory.getLogger(getClass());
172     }
173 
174     public VerifyMojo(Logger logger) {
175         this.logger = logger;
176     }
177 
178     @Override
179     public void execute() throws MojoExecutionException, MojoFailureException {
180         cli = commandLineOptions();
181         if (verifyParameters()) {
182             logDebugOrCliShowErrors(
183                     capitalizeFirstLetter(getPluginName()) + " report directory: " + getReportsDirectory());
184 
185             try {
186                 RunResult summary = existsSummaryFile() ? readSummary(summaryFile) : noTestsRun();
187 
188                 if (existsSummaryFiles()) {
189                     for (final File summaryFile : summaryFiles) {
190                         summary = summary.aggregate(readSummary(summaryFile));
191                     }
192                 }
193                 reportExecution(this, summary, getConsoleLogger(), getBooterForkException(summary));
194             } catch (IOException e) {
195                 throw new MojoExecutionException(e.getMessage(), e);
196             }
197         }
198     }
199 
200     private Exception getBooterForkException(RunResult summary) {
201         String firstForkExceptionFailureMessage = String.format("%s: ", SurefireBooterForkException.class.getName());
202         if (summary.getFailure() != null && summary.getFailure().contains(firstForkExceptionFailureMessage)) {
203             return new SurefireBooterForkException(
204                     summary.getFailure().substring(firstForkExceptionFailureMessage.length()));
205         }
206         return null;
207     }
208 
209     private PluginConsoleLogger getConsoleLogger() {
210         if (consoleLogger == null) {
211             synchronized (this) {
212                 if (consoleLogger == null) {
213                     consoleLogger = new PluginConsoleLogger(logger);
214                 }
215             }
216         }
217         return consoleLogger;
218     }
219 
220     private RunResult readSummary(File summaryFile) throws IOException {
221         return FailsafeSummaryXmlUtils.toRunResult(summaryFile);
222     }
223 
224     protected boolean verifyParameters() throws MojoFailureException {
225         if (isSkip() || isSkipTests() || isSkipITs() || isSkipExec()) {
226             getConsoleLogger().info("Tests are skipped.");
227             return false;
228         }
229 
230         if (!getTestClassesDirectory().exists()) {
231             if (getFailIfNoTests()) {
232                 throw new MojoFailureException("No tests to run!");
233             }
234         }
235 
236         if (!existsSummary()) {
237             getConsoleLogger().info("No tests to run.");
238             return false;
239         }
240 
241         if (failOnFlakeCount < 0) {
242             throw new MojoFailureException("Parameter \"failOnFlakeCount\" should not be negative.");
243         }
244 
245         return true;
246     }
247 
248     protected String getPluginName() {
249         return "failsafe";
250     }
251 
252     protected String[] getDefaultIncludes() {
253         return null;
254     }
255 
256     @Override
257     public boolean isSkipTests() {
258         return skipTests;
259     }
260 
261     @Override
262     public void setSkipTests(boolean skipTests) {
263         this.skipTests = skipTests;
264     }
265 
266     public boolean isSkipITs() {
267         return skipITs;
268     }
269 
270     public void setSkipITs(boolean skipITs) {
271         this.skipITs = skipITs;
272     }
273 
274     @Override
275     @Deprecated
276     public boolean isSkipExec() {
277         return skipExec;
278     }
279 
280     @Override
281     @Deprecated
282     public void setSkipExec(boolean skipExec) {
283         this.skipExec = skipExec;
284     }
285 
286     @Override
287     public boolean isSkip() {
288         return skip;
289     }
290 
291     @Override
292     public void setSkip(boolean skip) {
293         this.skip = skip;
294     }
295 
296     @Override
297     public boolean isTestFailureIgnore() {
298         return testFailureIgnore;
299     }
300 
301     @Override
302     public void setTestFailureIgnore(boolean testFailureIgnore) {
303         this.testFailureIgnore = testFailureIgnore;
304     }
305 
306     @Override
307     public File getBasedir() {
308         return basedir;
309     }
310 
311     @Override
312     public void setBasedir(File basedir) {
313         this.basedir = basedir;
314     }
315 
316     @Override
317     public File getTestClassesDirectory() {
318         return testClassesDirectory;
319     }
320 
321     @Override
322     public void setTestClassesDirectory(File testClassesDirectory) {
323         this.testClassesDirectory = testClassesDirectory;
324     }
325 
326     @Override
327     public File getReportsDirectory() {
328         return reportsDirectory;
329     }
330 
331     @Override
332     public void setReportsDirectory(File reportsDirectory) {
333         this.reportsDirectory = reportsDirectory;
334     }
335 
336     public File getSummaryFile() {
337         return summaryFile;
338     }
339 
340     public void setSummaryFile(File summaryFile) {
341         this.summaryFile = summaryFile;
342     }
343 
344     @Override
345     public boolean getFailIfNoTests() {
346         return failIfNoTests;
347     }
348 
349     @Override
350     public void setFailIfNoTests(boolean failIfNoTests) {
351         this.failIfNoTests = failIfNoTests;
352     }
353 
354     @Override
355     public int getFailOnFlakeCount() {
356         return failOnFlakeCount;
357     }
358 
359     @Override
360     public void setFailOnFlakeCount(int failOnFlakeCount) {
361         this.failOnFlakeCount = failOnFlakeCount;
362     }
363 
364     public MavenSession getSession() {
365         return session;
366     }
367 
368     public void setSession(MavenSession session) {
369         this.session = session;
370     }
371 
372     private boolean existsSummaryFile() {
373         return summaryFile != null && summaryFile.isFile();
374     }
375 
376     private boolean existsSummaryFiles() {
377         return summaryFiles != null && summaryFiles.length != 0;
378     }
379 
380     private boolean existsSummary() {
381         return existsSummaryFile() || existsSummaryFiles();
382     }
383 
384     private Collection<CommandLineOption> commandLineOptions() {
385         return SurefireHelper.commandLineOptions(session, getConsoleLogger());
386     }
387 
388     private void logDebugOrCliShowErrors(String s) {
389         SurefireHelper.logDebugOrCliShowErrors(s, getConsoleLogger(), cli);
390     }
391 }