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 java.io.File;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugin.MojoFailureException;
27  import org.apache.maven.plugin.surefire.AbstractSurefireMojoTest.Mojo;
28  import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
29  import org.apache.maven.surefire.api.suite.RunResult;
30  import org.apache.maven.surefire.api.testset.TestSetFailedException;
31  import org.apache.maven.surefire.booter.SurefireBooterForkException;
32  import org.codehaus.plexus.logging.Logger;
33  import org.junit.Rule;
34  import org.junit.Test;
35  import org.junit.rules.ExpectedException;
36  import org.mockito.ArgumentCaptor;
37  
38  import static java.util.Collections.addAll;
39  import static java.util.Collections.singleton;
40  import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
41  import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution;
42  import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
43  import static org.assertj.core.api.Assertions.assertThat;
44  import static org.hamcrest.Matchers.containsString;
45  import static org.junit.Assume.assumeTrue;
46  import static org.mockito.ArgumentMatchers.anyString;
47  import static org.mockito.Mockito.verify;
48  import static org.mockito.Mockito.when;
49  import static org.powermock.api.mockito.PowerMockito.doNothing;
50  import static org.powermock.api.mockito.PowerMockito.mock;
51  
52  /**
53   * Test of {@link SurefireHelper}.
54   */
55  public class SurefireHelperTest {
56  
57      @Rule
58      public ExpectedException e = ExpectedException.none();
59  
60      @Test
61      public void shouldReplaceForkNumberPath() {
62          File root = new File(System.getProperty("user.dir", ""));
63          File pathWithPlaceholder = new File(root, "${surefire.forkNumber}");
64          File changed = SurefireHelper.replaceForkThreadsInPath(pathWithPlaceholder, 5);
65          assertThat(changed.getPath()).isEqualTo(new File(root, "5").getPath());
66      }
67  
68      @Test
69      public void shouldReplaceLongForkNumberPath() {
70          File root = new File(System.getProperty("user.dir", ""));
71          File subDir = new File(root, "reports-${surefire.forkNumber}");
72          File pathWithPlaceholder = new File(subDir, "subfolder");
73          File changed = SurefireHelper.replaceForkThreadsInPath(pathWithPlaceholder, 5);
74          assertThat(changed.getPath()).isEqualTo(new File(new File(root, "reports-5"), "subfolder").getPath());
75      }
76  
77      @Test
78      public void shouldBeThreeDumpFiles() {
79          String[] dumps = SurefireHelper.getDumpFilesToPrint();
80          assertThat(dumps).hasSize(4);
81          assertThat(dumps).doesNotHaveDuplicates();
82          List<String> onlyStrings = new ArrayList<>();
83          addAll(onlyStrings, dumps);
84          onlyStrings.removeAll(singleton((String) null));
85          assertThat(onlyStrings).hasSize(4);
86      }
87  
88      @Test
89      public void shouldCloneDumpFiles() {
90          String[] dumps1 = SurefireHelper.getDumpFilesToPrint();
91          String[] dumps2 = SurefireHelper.getDumpFilesToPrint();
92          assertThat(dumps1).isNotSameAs(dumps2);
93      }
94  
95      @Test
96      public void testConstants() {
97          assertThat(SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER)
98                  .isEqualTo(SurefireHelper.DUMP_FILE_PREFIX + "%d.dumpstream");
99  
100         assertThat(String.format(SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER, 5))
101                 .endsWith("-jvmRun5.dumpstream");
102     }
103 
104     @Test
105     public void shouldEscapeWindowsPath() {
106         assumeTrue(IS_OS_WINDOWS);
107         String root = "X:\\path\\to\\project\\";
108         String pathToJar = "target\\surefire\\surefirebooter4942721306300108667.jar";
109         @SuppressWarnings("checkstyle:magicnumber")
110         int projectNameLength = 247 - root.length() - pathToJar.length();
111         StringBuilder projectFolder = new StringBuilder();
112         for (int i = 0; i < projectNameLength; i++) {
113             projectFolder.append('x');
114         }
115         String path = root + projectFolder + "\\" + pathToJar;
116         String escaped = escapeToPlatformPath(path);
117         assertThat(escaped).isEqualTo("\\\\?\\" + path);
118 
119         path = root + "\\" + pathToJar;
120         escaped = escapeToPlatformPath(path);
121         assertThat(escaped).isEqualTo(root + "\\" + pathToJar);
122     }
123 
124     @Test
125     public void shouldHandleFailWithoutExitCode() throws Exception {
126         RunResult summary = new RunResult(0, 0, 0, 0);
127         Mojo plugin = new Mojo();
128         plugin.setTestFailureIgnore(true);
129 
130         Logger logger = mock(Logger.class);
131         when(logger.isErrorEnabled()).thenReturn(true);
132         doNothing().when(logger).error(anyString());
133         TestSetFailedException exc = new TestSetFailedException("failure");
134         reportExecution(plugin, summary, new PluginConsoleLogger(logger), exc);
135         ArgumentCaptor<String> errorMessage = ArgumentCaptor.forClass(String.class);
136         verify(logger).error(errorMessage.capture());
137         assertThat(errorMessage.getValue()).contains("failure");
138     }
139 
140     @Test
141     public void shouldHandleFailIfJvmNonZeroExitCode() throws Exception {
142         RunResult summary = new RunResult(0, 0, 0, 0);
143         Mojo plugin = new Mojo();
144         plugin.setTestFailureIgnore(true);
145 
146         SurefireBooterForkException exc = new SurefireBooterForkException("Unrecognized option: -Xxxx");
147         e.expect(MojoExecutionException.class);
148         e.expectMessage(containsString("Unrecognized option: -Xxxx"));
149         reportExecution(plugin, summary, new PluginConsoleLogger(mock(Logger.class)), exc);
150     }
151 
152     @Test
153     public void shouldHandleFailIfNoTests() throws Exception {
154         RunResult summary = new RunResult(0, 0, 0, 0);
155         Mojo plugin = new Mojo();
156         plugin.setFailIfNoTests(true);
157         e.expect(MojoFailureException.class);
158         e.expectMessage("No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)");
159         reportExecution(plugin, summary, null, null);
160     }
161 
162     @Test
163     public void shouldHandleTestFailure() throws Exception {
164         RunResult summary = new RunResult(1, 0, 1, 0);
165         e.expect(MojoFailureException.class);
166         e.expectMessage("There are test failures.\n\nPlease refer to null "
167                 + "for the individual test results.\nPlease refer to dump files (if any exist) "
168                 + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream.");
169         reportExecution(new Mojo(), summary, null, null);
170     }
171 
172     @Test
173     public void failsIfThereAreTooManyFlakes() throws Exception {
174         RunResult summary = new RunResult(1, 0, 0, 0, 1);
175         Mojo reportParameters = new Mojo();
176         reportParameters.setFailOnFlakeCount(1);
177         e.expect(MojoFailureException.class);
178         e.expectMessage("There is 1 flake and failOnFlakeCount is set to 1.\n\nPlease refer to null "
179                 + "for the individual test results.\nPlease refer to dump files (if any exist) "
180                 + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream.");
181         reportExecution(reportParameters, summary, null, null);
182     }
183 
184     @Test
185     public void reportsFailuresAndFlakes() throws Exception {
186         RunResult summary = new RunResult(1, 0, 1, 0, 2);
187         Mojo reportParameters = new Mojo();
188         reportParameters.setFailOnFlakeCount(1);
189         e.expect(MojoFailureException.class);
190         e.expectMessage("There are test failures.\nThere are 2 flakes and failOnFlakeCount is set to 1."
191                 + "\n\nPlease refer to null "
192                 + "for the individual test results.\nPlease refer to dump files (if any exist) "
193                 + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream.");
194         reportExecution(reportParameters, summary, null, null);
195     }
196 
197     @Test
198     public void passesIfFlakesAreWithinThreshold() throws Exception {
199         RunResult summary = new RunResult(1, 0, 0, 0, 1);
200         reportExecution(new Mojo(), summary, null, null);
201     }
202 }