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