1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache;
20
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24
25 import org.apache.maven.buildcache.xml.Build;
26 import org.apache.maven.execution.ExecutionEvent;
27 import org.apache.maven.execution.MavenSession;
28 import org.apache.maven.lifecycle.DefaultLifecycles;
29 import org.apache.maven.lifecycle.Lifecycle;
30 import org.apache.maven.lifecycle.internal.stub.LifecyclesTestUtils;
31 import org.apache.maven.plugin.MojoExecution;
32 import org.apache.maven.project.MavenProject;
33 import org.jetbrains.annotations.NotNull;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.params.ParameterizedTest;
37 import org.junit.jupiter.params.provider.ValueSource;
38
39 import static java.util.Collections.emptyList;
40 import static java.util.Collections.singletonList;
41 import static org.assertj.core.api.Assertions.assertThat;
42 import static org.junit.jupiter.api.Assertions.assertEquals;
43 import static org.junit.jupiter.api.Assertions.assertFalse;
44 import static org.junit.jupiter.api.Assertions.assertThrows;
45 import static org.junit.jupiter.api.Assertions.assertTrue;
46 import static org.junit.jupiter.api.Assumptions.assumeTrue;
47 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.when;
50
51 class LifecyclePhasesHelperTest {
52
53 private LifecyclePhasesHelper lifecyclePhasesHelper;
54 private MavenProject projectMock;
55 private DefaultLifecycles defaultLifecycles;
56 private Lifecycle cleanLifecycle;
57
58 @BeforeEach
59 void setUp() {
60
61 defaultLifecycles = LifecyclesTestUtils.createDefaultLifecycles();
62 cleanLifecycle = defaultLifecycles.getLifeCycles().stream()
63 .filter(lifecycle -> lifecycle.getId().equals("clean"))
64 .findFirst()
65 .orElseThrow(() -> new RuntimeException("Clean phase not found"));
66
67 MavenSession session = mock(MavenSession.class, RETURNS_DEEP_STUBS);
68 lifecyclePhasesHelper = new LifecyclePhasesHelper(session, defaultLifecycles, cleanLifecycle);
69
70 projectMock = mock(MavenProject.class);
71 }
72
73
74
75
76 @Test
77 void resolveHighestLifecyclePhaseNormal() {
78 String phase = lifecyclePhasesHelper.resolveHighestLifecyclePhase(
79 projectMock,
80 Arrays.asList(
81 mockedMojoExecution("clean"), mockedMojoExecution("compile"), mockedMojoExecution("install")));
82 assertEquals("install", phase);
83 }
84
85
86
87
88 @Test
89 void resolveHighestLifecyclePhaseForked() {
90
91 MojoExecution origin = mockedMojoExecution("install");
92 publishForkedProjectEvent(origin);
93
94 String phase = lifecyclePhasesHelper.resolveHighestLifecyclePhase(
95 projectMock, Arrays.asList(mockedMojoExecution(null)));
96
97 assertEquals("install", phase);
98 }
99
100
101
102
103 @Test
104 void isLaterPhaseThanClean() {
105 List<Lifecycle> afterClean = new ArrayList<>(defaultLifecycles.getLifeCycles());
106
107 assumeTrue(afterClean.remove(cleanLifecycle));
108 assumeTrue(afterClean.size() > 0);
109
110 assertTrue(afterClean.stream()
111 .flatMap(it -> it.getPhases().stream())
112 .allMatch(lifecyclePhasesHelper::isLaterPhaseThanClean));
113 }
114
115
116
117
118 @Test
119 void isLaterPhaseThanCleanNegative() {
120 assertTrue(cleanLifecycle.getPhases().stream().noneMatch(lifecyclePhasesHelper::isLaterPhaseThanClean));
121 }
122
123 @Test
124 void isLaterPhaseThanBuild() {
125 List<Lifecycle> afterClean = new ArrayList<>(defaultLifecycles.getLifeCycles());
126
127 assumeTrue(afterClean.remove(cleanLifecycle));
128 assumeTrue(afterClean.size() > 0);
129
130 Build buildMock = mock(Build.class);
131 when(buildMock.getHighestCompletedGoal()).thenReturn("clean");
132
133 assertTrue(afterClean.stream()
134 .flatMap(it -> it.getPhases().stream())
135 .allMatch(phase -> lifecyclePhasesHelper.isLaterPhaseThanBuild(phase, buildMock)));
136 }
137
138 @Test
139 void isLaterPhaseThanBuildNegative() {
140 List<Lifecycle> afterClean = new ArrayList<>(defaultLifecycles.getLifeCycles());
141
142 assumeTrue(afterClean.remove(cleanLifecycle));
143 assumeTrue(afterClean.size() > 0);
144
145 Build buildMock = mock(Build.class);
146 when(buildMock.getHighestCompletedGoal()).thenReturn("install");
147
148 assertFalse(afterClean.stream()
149 .flatMap(it -> it.getPhases().stream())
150 .allMatch(phase -> lifecyclePhasesHelper.isLaterPhaseThanBuild(phase, buildMock)));
151 }
152
153 @Test
154 void isLaterPhase() {
155 assertTrue(lifecyclePhasesHelper.isLaterPhase("install", "compile"));
156 assertTrue(lifecyclePhasesHelper.isLaterPhase("package", "clean"));
157 assertTrue(lifecyclePhasesHelper.isLaterPhase("site", "install"));
158 assertFalse(lifecyclePhasesHelper.isLaterPhase("test", "site"));
159 assertFalse(lifecyclePhasesHelper.isLaterPhase("clean", "site"));
160
161 assertThrows(IllegalArgumentException.class, () -> {
162 lifecyclePhasesHelper.isLaterPhase("install", null);
163 });
164
165 assertThrows(IllegalArgumentException.class, () -> {
166 lifecyclePhasesHelper.isLaterPhase("install", "unknown phase");
167 });
168
169 assertThrows(IllegalArgumentException.class, () -> {
170 lifecyclePhasesHelper.isLaterPhase("unknown phase", "install");
171 });
172 }
173
174 @Test
175 void getCleanSegment() {
176 MojoExecution clean = mockedMojoExecution("clean");
177 List<MojoExecution> cleanSegment = lifecyclePhasesHelper.getCleanSegment(
178 projectMock, Arrays.asList(clean, mockedMojoExecution("compile"), mockedMojoExecution("install")));
179 assertEquals(singletonList(clean), cleanSegment);
180 }
181
182
183
184
185 @Test
186 void getEmptyCleanSegment() {
187 List<MojoExecution> cleanSegment = lifecyclePhasesHelper.getCleanSegment(
188 projectMock, Arrays.asList(mockedMojoExecution("compile"), mockedMojoExecution("install")));
189 assertEquals(emptyList(), cleanSegment);
190 }
191
192
193
194
195 @Test
196 void getEmptyCleanSegmentIfForked() {
197
198 MojoExecution origin = mockedMojoExecution("install");
199 publishForkedProjectEvent(origin);
200
201 List<MojoExecution> cleanSegment = lifecyclePhasesHelper.getCleanSegment(
202 projectMock,
203 Arrays.asList(
204
205 mockedMojoExecution(null), mockedMojoExecution(null)));
206
207 assertEquals(emptyList(), cleanSegment);
208 }
209
210
211
212
213 @Test
214 void getCleanSegmentForkedAnyLifecyclePhase() {
215 MojoExecution origin = mockedMojoExecution("install");
216 publishForkedProjectEvent(origin);
217
218 List<MojoExecution> cleanSegment = lifecyclePhasesHelper.getCleanSegment(
219 projectMock,
220 Arrays.asList(
221
222 mockedMojoExecution("clean")));
223
224 assertEquals(emptyList(), cleanSegment);
225 }
226
227 @Test
228 void testCachedSegment() {
229 MojoExecution compile = mockedMojoExecution("compile");
230 MojoExecution test = mockedMojoExecution("test");
231 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, mockedMojoExecution("install"));
232
233 Build build = mock(Build.class);
234 when(build.getHighestCompletedGoal()).thenReturn("test");
235
236 List<MojoExecution> cachedSegment = lifecyclePhasesHelper.getCachedSegment(projectMock, mojoExecutions, build);
237
238 assertThat(cachedSegment).containsExactly(compile, test);
239 }
240
241 @Test
242 void testEmptyCachedSegment() {
243 MojoExecution compile = mockedMojoExecution("compile");
244 MojoExecution test = mockedMojoExecution("test");
245 MojoExecution install = mockedMojoExecution("install");
246 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, install);
247
248 Build build = mock(Build.class);
249 when(build.getHighestCompletedGoal()).thenReturn("clean");
250
251 List<MojoExecution> cachedSegment = lifecyclePhasesHelper.getCachedSegment(projectMock, mojoExecutions, build);
252
253 assertThat(cachedSegment).isEmpty();
254 }
255
256 @Test
257 void testCachedSegmentForked() {
258 MojoExecution me1 = mockedMojoExecution(null);
259 MojoExecution me2 = mockedMojoExecution(null);
260
261 List<MojoExecution> mojoExecutions = Arrays.asList(me1, me2);
262
263 MojoExecution origin = mockedMojoExecution("install");
264 publishForkedProjectEvent(origin);
265
266 Build build = mock(Build.class);
267 when(build.getHighestCompletedGoal()).thenReturn("site");
268
269 List<MojoExecution> cachedSegment = lifecyclePhasesHelper.getCachedSegment(projectMock, mojoExecutions, build);
270
271 assertEquals(mojoExecutions, cachedSegment);
272 }
273
274 @ParameterizedTest
275 @ValueSource(strings = {"install", "site"})
276 void testAllInCachedSegment() {
277 MojoExecution compile = mockedMojoExecution("compile");
278 MojoExecution test = mockedMojoExecution("test");
279 MojoExecution install = mockedMojoExecution("install");
280 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, install);
281
282 Build build = mock(Build.class);
283 when(build.getHighestCompletedGoal()).thenReturn("site");
284
285 List<MojoExecution> cachedSegment = lifecyclePhasesHelper.getCachedSegment(projectMock, mojoExecutions, build);
286
287 assertEquals(mojoExecutions, cachedSegment);
288 }
289
290 @Test
291 void testPostCachedSegment() {
292 MojoExecution compile = mockedMojoExecution("compile");
293 MojoExecution test = mockedMojoExecution("test");
294 MojoExecution install = mockedMojoExecution("install");
295 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, install);
296
297 Build build = mock(Build.class);
298 when(build.getHighestCompletedGoal()).thenReturn("compile");
299
300 List<MojoExecution> notCachedSegment =
301 lifecyclePhasesHelper.getPostCachedSegment(projectMock, mojoExecutions, build);
302
303 assertThat(notCachedSegment).containsExactly(test, install);
304 }
305
306 @Test
307 void testAllPostCachedSegment() {
308 MojoExecution compile = mockedMojoExecution("compile");
309 MojoExecution test = mockedMojoExecution("test");
310 MojoExecution install = mockedMojoExecution("install");
311 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, install);
312
313 Build build = mock(Build.class);
314 when(build.getHighestCompletedGoal()).thenReturn("clean");
315
316 List<MojoExecution> notCachedSegment =
317 lifecyclePhasesHelper.getPostCachedSegment(projectMock, mojoExecutions, build);
318
319 assertThat(notCachedSegment).isEqualTo(mojoExecutions);
320 }
321
322 @Test
323 void testPostCachedSegmentForked() {
324 MojoExecution me1 = mockedMojoExecution(null);
325 MojoExecution me2 = mockedMojoExecution(null);
326
327 List<MojoExecution> mojoExecutions = Arrays.asList(me1, me2);
328
329 MojoExecution origin = mockedMojoExecution("install");
330 publishForkedProjectEvent(origin);
331
332 Build build = mock(Build.class);
333 when(build.getHighestCompletedGoal()).thenReturn("package");
334
335 List<MojoExecution> cachedSegment =
336 lifecyclePhasesHelper.getPostCachedSegment(projectMock, mojoExecutions, build);
337
338 assertThat(cachedSegment).isEqualTo(mojoExecutions);
339 }
340
341 @ParameterizedTest
342 @ValueSource(strings = {"install", "site"})
343 void testEmptyPostCachedSegmentInclusive() {
344 MojoExecution compile = mockedMojoExecution("compile");
345 MojoExecution test = mockedMojoExecution("test");
346 MojoExecution install = mockedMojoExecution("install");
347 List<MojoExecution> mojoExecutions = Arrays.asList(compile, test, install);
348
349 Build cachedBuild = mock(Build.class);
350 when(cachedBuild.getHighestCompletedGoal()).thenReturn("install");
351
352 List<MojoExecution> notCachedSegment =
353 lifecyclePhasesHelper.getPostCachedSegment(projectMock, mojoExecutions, cachedBuild);
354
355 assertThat(notCachedSegment).isEmpty();
356 }
357
358 private void publishForkedProjectEvent(MojoExecution origin) {
359
360 ExecutionEvent eventMock = mock(ExecutionEvent.class);
361
362 when(eventMock.getProject()).thenReturn(projectMock);
363 when(eventMock.getMojoExecution()).thenReturn(origin);
364 when(eventMock.getType()).thenReturn(ExecutionEvent.Type.ForkedProjectStarted);
365
366 lifecyclePhasesHelper.forkedProjectStarted(eventMock);
367 }
368
369 @NotNull
370 private static MojoExecution mockedMojoExecution(String phase) {
371 MojoExecution mojoExecution = mock(MojoExecution.class);
372 when(mojoExecution.getLifecyclePhase()).thenReturn(phase);
373 when(mojoExecution.toString()).thenReturn(phase);
374 return mojoExecution;
375 }
376 }