1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache.xml;
20
21 import javax.inject.Provider;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.nio.file.AccessMode;
28 import java.nio.file.FileSystem;
29 import java.nio.file.Path;
30 import java.nio.file.spi.FileSystemProvider;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.Properties;
37 import java.util.stream.Collectors;
38
39 import org.apache.commons.lang3.tuple.Pair;
40 import org.apache.maven.buildcache.DefaultPluginScanConfig;
41 import org.apache.maven.buildcache.hash.HashFactory;
42 import org.apache.maven.buildcache.xml.config.Configuration;
43 import org.apache.maven.buildcache.xml.config.Remote;
44 import org.apache.maven.execution.MavenExecutionRequest;
45 import org.apache.maven.execution.MavenSession;
46 import org.apache.maven.model.Plugin;
47 import org.apache.maven.model.PluginExecution;
48 import org.apache.maven.plugin.MojoExecution;
49 import org.apache.maven.rtinfo.RuntimeInformation;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52 import org.junit.jupiter.api.extension.ExtendWith;
53 import org.mockito.ArgumentMatchers;
54 import org.mockito.Mock;
55 import org.mockito.Mockito;
56 import org.mockito.junit.jupiter.MockitoExtension;
57 import org.mockito.junit.jupiter.MockitoSettings;
58 import org.mockito.quality.Strictness;
59
60 import static org.junit.jupiter.api.Assertions.assertEquals;
61 import static org.junit.jupiter.api.Assertions.assertFalse;
62 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
63 import static org.junit.jupiter.api.Assertions.assertNull;
64 import static org.junit.jupiter.api.Assertions.assertTrue;
65 import static org.mockito.Mockito.doThrow;
66 import static org.mockito.Mockito.mock;
67 import static org.mockito.Mockito.when;
68
69 @ExtendWith(MockitoExtension.class)
70 @MockitoSettings(strictness = Strictness.LENIENT)
71 @SuppressWarnings("unchecked")
72 class CacheConfigImplTest {
73
74 @Mock
75 private MavenSession mavenSession;
76
77 @Mock
78 private Properties mockProperties;
79
80 @Mock
81 private MavenExecutionRequest mockMavenExecutionRequest;
82
83 @Mock
84 private RuntimeInformation rtInfo;
85
86 @Mock
87 private XmlService xmlService;
88
89 @Mock
90 private File rootConfigFile;
91
92 private org.apache.maven.buildcache.xml.config.CacheConfig testCacheConfig;
93 private CacheConfigImpl testObject;
94
95 @BeforeEach
96 void setUp() throws IOException {
97
98
99
100
101
102 when(mavenSession.getRequest()).thenReturn(mockMavenExecutionRequest);
103 when(mavenSession.getUserProperties()).thenReturn(mockProperties);
104 when(mavenSession.getSystemProperties()).thenReturn(mockProperties);
105
106
107 when(rtInfo.isMavenVersion(ArgumentMatchers.anyString())).thenReturn(true);
108
109
110 deepMockConfigFile(rootConfigFile, true);
111 when(mockMavenExecutionRequest.getMultiModuleProjectDirectory()).thenReturn(rootConfigFile);
112
113 testCacheConfig = new XmlService().loadCacheConfig("<cache></cache>".getBytes());
114 when(xmlService.loadCacheConfig(rootConfigFile)).thenReturn(testCacheConfig);
115
116 Provider<MavenSession> provider = (() -> mavenSession);
117
118 testObject = new CacheConfigImpl(xmlService, provider, rtInfo);
119 }
120
121 private static void deepMockConfigFile(File mockFile, boolean exists) throws IOException {
122 Path mockPath = mock(Path.class);
123 when(mockFile.toPath()).thenReturn(mockPath);
124 when(mockPath.toFile()).thenReturn(mockFile);
125 when(mockPath.resolve(ArgumentMatchers.anyString())).thenReturn(mockPath);
126
127
128
129 FileSystem mockFileSystem = mock(FileSystem.class);
130 when(mockPath.getFileSystem()).thenReturn(mockFileSystem);
131 FileSystemProvider mockProvider = mock(FileSystemProvider.class);
132 when(mockFileSystem.provider()).thenReturn(mockProvider);
133
134
135 if (!exists) {
136 doThrow(new IOException("mock IOException"))
137 .when(mockProvider)
138 .checkAccess(ArgumentMatchers.eq(mockPath), ArgumentMatchers.any(AccessMode.class));
139 }
140
141
142
143 Optional<Method> methodToMock = Arrays.stream(FileSystemProvider.class.getDeclaredMethods())
144 .filter(method -> "exists".equals(method.getName()))
145 .findAny();
146 if (methodToMock.isPresent()) {
147 Class<?>[] paramTypes = methodToMock.get().getParameterTypes();
148 Object[] params = Arrays.stream(paramTypes).map(Mockito::any).toArray();
149 try {
150 Mockito.when(methodToMock.get().invoke(mockProvider, params)).thenReturn(exists);
151 } catch (IllegalAccessException | InvocationTargetException e) {
152 throw new RuntimeException("Error while mocking the 'exists' method from FileSystemProvider", e);
153 }
154 }
155 }
156
157 private void assertDefaults() {
158 assertDefaults(Collections.emptyMap());
159 }
160
161 private void assertDefaults(Pair<String, Runnable>... overrides) {
162 assertDefaults(Arrays.stream(overrides).collect(Collectors.toMap(Pair::getKey, Pair::getValue)));
163 }
164
165 private void assertDefaults(Map<String, Runnable> overrides) {
166 Map<String, Runnable> asserts = new HashMap<>();
167 asserts.put("adjustMetaInfVersion", () -> assertFalse(testObject.adjustMetaInfVersion()));
168 asserts.put("calculateProjectVersionChecksum", () -> assertFalse(testObject.calculateProjectVersionChecksum()));
169 asserts.put("canIgnore", () -> assertFalse(testObject.canIgnore(mock(MojoExecution.class))));
170 asserts.put("getAlwaysRunPlugins", () -> assertNull(testObject.getAlwaysRunPlugins()));
171 asserts.put("getAttachedOutputs", () -> assertEquals(Collections.emptyList(), testObject.getAttachedOutputs()));
172 asserts.put("getBaselineCacheUrl", () -> assertNull(testObject.getBaselineCacheUrl()));
173 asserts.put("getDefaultGlob", () -> assertEquals("*", testObject.getDefaultGlob()));
174 asserts.put(
175 "getEffectivePomExcludeProperties",
176 () -> assertEquals(
177 Collections.emptyList(), testObject.getEffectivePomExcludeProperties(mock(Plugin.class))));
178 asserts.put("getExcludePatterns", () -> assertEquals(Collections.emptyList(), testObject.getExcludePatterns()));
179 asserts.put(
180 "getExecutionDirScanConfig",
181 () -> assertInstanceOf(
182 DefaultPluginScanConfig.class,
183 testObject.getExecutionDirScanConfig(mock(Plugin.class), mock(PluginExecution.class))));
184 asserts.put(
185 "getGlobalExcludePaths",
186 () -> assertEquals(Collections.emptyList(), testObject.getGlobalExcludePaths()));
187 asserts.put(
188 "getGlobalIncludePaths",
189 () -> assertEquals(Collections.emptyList(), testObject.getGlobalIncludePaths()));
190 asserts.put("getHashFactory", () -> assertEquals(HashFactory.XX, testObject.getHashFactory()));
191 asserts.put("getId", () -> assertEquals("cache", testObject.getId()));
192 asserts.put("getLocalRepositoryLocation", () -> assertNull(testObject.getLocalRepositoryLocation()));
193 asserts.put(
194 "getLoggedProperties",
195 () -> assertEquals(Collections.emptyList(), testObject.getLoggedProperties(mock(MojoExecution.class))));
196 asserts.put("getMaxLocalBuildsCached", () -> assertEquals(3, testObject.getMaxLocalBuildsCached()));
197 asserts.put("getMultiModule", () -> assertNull(testObject.getMultiModule()));
198 asserts.put(
199 "getNologProperties",
200 () -> assertEquals(Collections.emptyList(), testObject.getNologProperties(mock(MojoExecution.class))));
201 asserts.put(
202 "getPluginDirScanConfig",
203 () -> assertInstanceOf(
204 DefaultPluginScanConfig.class, testObject.getPluginDirScanConfig(mock(Plugin.class))));
205 asserts.put(
206 "getTrackedProperties",
207 () -> assertEquals(
208 Collections.emptyList(), testObject.getTrackedProperties(mock(MojoExecution.class))));
209 asserts.put("getTransport", () -> assertEquals("resolver", testObject.getTransport()));
210 asserts.put("getUrl", () -> assertNull(testObject.getUrl()));
211 asserts.put("isBaselineDiffEnabled", () -> assertFalse(testObject.isBaselineDiffEnabled()));
212 asserts.put("isEnabled", () -> assertTrue(testObject.isEnabled()));
213 asserts.put("isFailFast", () -> assertFalse(testObject.isFailFast()));
214 asserts.put("isForcedExecution", () -> assertFalse(testObject.isForcedExecution(null)));
215 asserts.put("isLazyRestore", () -> assertFalse(testObject.isLazyRestore()));
216 asserts.put("isLogAllProperties", () -> assertFalse(testObject.isLogAllProperties(null)));
217 asserts.put("isProcessPlugins", () -> assertEquals("true", testObject.isProcessPlugins()));
218 asserts.put("isRemoteCacheEnabled", () -> assertFalse(testObject.isRemoteCacheEnabled()));
219 asserts.put("isRestoreGeneratedSources", () -> assertTrue(testObject.isRestoreGeneratedSources()));
220 asserts.put("isSaveToRemote", () -> assertFalse(testObject.isSaveToRemote()));
221 asserts.put("isSaveToRemoteFinal", () -> assertFalse(testObject.isSaveToRemoteFinal()));
222 asserts.put("isSkipCache", () -> assertFalse(testObject.isSkipCache()));
223
224 asserts.putAll(overrides);
225
226 asserts.values().forEach(Runnable::run);
227 }
228
229 @Test
230 void testInitializationInvalidMavenVersion() {
231 when(rtInfo.isMavenVersion(ArgumentMatchers.anyString())).thenReturn(false);
232
233 assertEquals(CacheState.DISABLED, testObject.initialize());
234 }
235
236 @Test
237 void testInitializationDisabledUserProperty() {
238 when(mockProperties.getProperty(CacheConfigImpl.CACHE_ENABLED_PROPERTY_NAME))
239 .thenReturn("false");
240
241 assertEquals(CacheState.DISABLED, testObject.initialize());
242 }
243
244 @Test
245 void testInitializationDisabledSystemProperty() {
246 when(mockProperties.getProperty(CacheConfigImpl.CACHE_ENABLED_PROPERTY_NAME))
247 .thenReturn(null)
248 .thenReturn("false");
249
250 assertEquals(CacheState.DISABLED, testObject.initialize());
251 }
252
253 @Test
254 void testInitializationDisabledInXML() {
255 Configuration configuration = new Configuration();
256 configuration.setEnabled(false);
257 testCacheConfig.setConfiguration(configuration);
258
259 assertEquals(CacheState.DISABLED, testObject.initialize());
260 }
261
262 @Test
263 void testInitializationNonExistantXMLFromProperty() {
264 when(mockProperties.getProperty(CacheConfigImpl.CONFIG_PATH_PROPERTY_NAME))
265 .thenReturn("does-not-exist");
266
267 assertEquals(CacheState.INITIALIZED, testObject.initialize());
268 assertDefaults();
269 }
270
271 @Test
272 void testInitializationNonExistantXMLFromRoot() throws IOException {
273 deepMockConfigFile(rootConfigFile, false);
274
275 assertEquals(CacheState.INITIALIZED, testObject.initialize());
276 assertDefaults();
277 }
278
279 @Test
280 void testInitializationExplicitlyEnabledUserPropertyOverridesXML() {
281 Configuration configuration = new Configuration();
282 configuration.setEnabled(false);
283 testCacheConfig.setConfiguration(configuration);
284 when(mockProperties.getProperty(CacheConfigImpl.CACHE_ENABLED_PROPERTY_NAME))
285 .thenReturn("true");
286
287 assertEquals(CacheState.INITIALIZED, testObject.initialize());
288 assertDefaults();
289 }
290
291 @Test
292 void testRemoteEnableInXMLButNoURL() {
293 Configuration configuration = new Configuration();
294 Remote remote = new Remote();
295 remote.setEnabled(true);
296 configuration.setRemote(remote);
297 testCacheConfig.setConfiguration(configuration);
298
299 assertEquals(CacheState.INITIALIZED, testObject.initialize());
300 assertDefaults();
301 }
302
303 @Test
304 void testRemoteEnableInXMLWithURL() {
305 Configuration configuration = new Configuration();
306 Remote remote = new Remote();
307 remote.setEnabled(true);
308 remote.setUrl("dummy.url.xyz");
309 configuration.setRemote(remote);
310 testCacheConfig.setConfiguration(configuration);
311
312 assertEquals(CacheState.INITIALIZED, testObject.initialize());
313 assertDefaults(
314 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
315 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())));
316 }
317
318 @Test
319 void testRemoteEnableByUserPropertyOverrideNoURL() {
320 when(mockProperties.getProperty(CacheConfigImpl.REMOTE_ENABLED_PROPERTY_NAME))
321 .thenReturn("true");
322
323 assertEquals(CacheState.INITIALIZED, testObject.initialize());
324 assertDefaults();
325 }
326
327 @Test
328 void testRemoteEnableByUserPropertyOverrideWithURL() {
329 Configuration configuration = new Configuration();
330 Remote remote = new Remote();
331 remote.setUrl("dummy.url.xyz");
332 configuration.setRemote(remote);
333 testCacheConfig.setConfiguration(configuration);
334 when(mockProperties.getProperty(CacheConfigImpl.REMOTE_ENABLED_PROPERTY_NAME))
335 .thenReturn("true");
336
337 assertEquals(CacheState.INITIALIZED, testObject.initialize());
338 assertDefaults(
339 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
340 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())));
341 }
342
343 @Test
344 void testRemoteDisableByUserPropertyOverride() {
345 Configuration configuration = new Configuration();
346 Remote remote = new Remote();
347 remote.setUrl("dummy.url.xyz");
348 remote.setEnabled(true);
349 configuration.setRemote(remote);
350 testCacheConfig.setConfiguration(configuration);
351 when(mockProperties.getProperty(CacheConfigImpl.REMOTE_ENABLED_PROPERTY_NAME))
352 .thenReturn("false");
353
354 assertEquals(CacheState.INITIALIZED, testObject.initialize());
355 assertDefaults(Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())));
356 }
357
358 @Test
359 void testRemoveSaveEnabledInXML() {
360 Configuration configuration = new Configuration();
361 Remote remote = new Remote();
362 remote.setUrl("dummy.url.xyz");
363 remote.setEnabled(true);
364 remote.setSaveToRemote(true);
365 configuration.setRemote(remote);
366 testCacheConfig.setConfiguration(configuration);
367
368 assertEquals(CacheState.INITIALIZED, testObject.initialize());
369 assertDefaults(
370 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
371 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())),
372 Pair.of("isSaveToRemote", () -> assertTrue(testObject.isSaveToRemote())));
373 }
374
375 @Test
376 void testRemoveSaveEnabledByUserProperty() {
377 Configuration configuration = new Configuration();
378 Remote remote = new Remote();
379 remote.setUrl("dummy.url.xyz");
380 remote.setEnabled(true);
381 configuration.setRemote(remote);
382 testCacheConfig.setConfiguration(configuration);
383 when(mockProperties.getProperty(CacheConfigImpl.SAVE_TO_REMOTE_PROPERTY_NAME))
384 .thenReturn("true");
385
386 assertEquals(CacheState.INITIALIZED, testObject.initialize());
387 assertDefaults(
388 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
389 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())),
390 Pair.of("isSaveToRemote", () -> assertTrue(testObject.isSaveToRemote())));
391 }
392
393 @Test
394 void testRemoveSaveDisabledByUserProperty() {
395 Configuration configuration = new Configuration();
396 Remote remote = new Remote();
397 remote.setUrl("dummy.url.xyz");
398 remote.setEnabled(true);
399 remote.setSaveToRemote(true);
400 configuration.setRemote(remote);
401 testCacheConfig.setConfiguration(configuration);
402 when(mockProperties.getProperty(CacheConfigImpl.SAVE_TO_REMOTE_PROPERTY_NAME))
403 .thenReturn("false");
404
405 assertEquals(CacheState.INITIALIZED, testObject.initialize());
406 assertDefaults(
407 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
408 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())));
409 }
410
411 @Test
412 void testRemoteSaveIgnoredWhenRemoteDisabledInXML() {
413 Configuration configuration = new Configuration();
414 Remote remote = new Remote();
415 remote.setSaveToRemote(true);
416 configuration.setRemote(remote);
417 testCacheConfig.setConfiguration(configuration);
418
419 assertEquals(CacheState.INITIALIZED, testObject.initialize());
420 assertDefaults();
421 }
422
423 @Test
424 void testRemoteSaveIgnoredWhenRemoteDisabledUserProperty() {
425 when(mockProperties.getProperty(CacheConfigImpl.SAVE_TO_REMOTE_PROPERTY_NAME))
426 .thenReturn("true");
427
428 assertEquals(CacheState.INITIALIZED, testObject.initialize());
429 assertDefaults();
430 }
431
432 @Test
433 void testRemoteSaveIgnoredWhenRemoteDisabledByUserPropertyOverride() {
434 Configuration configuration = new Configuration();
435 Remote remote = new Remote();
436 remote.setUrl("dummy.url.xyz");
437 remote.setEnabled(true);
438 remote.setSaveToRemote(true);
439 configuration.setRemote(remote);
440 testCacheConfig.setConfiguration(configuration);
441 when(mockProperties.getProperty(CacheConfigImpl.REMOTE_ENABLED_PROPERTY_NAME))
442 .thenReturn("false");
443
444 assertEquals(CacheState.INITIALIZED, testObject.initialize());
445 assertDefaults(Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())));
446 }
447
448 @Test
449 void testRemoveSaveFinalEnabledByUserProperty() {
450 Configuration configuration = new Configuration();
451 Remote remote = new Remote();
452 remote.setUrl("dummy.url.xyz");
453 remote.setEnabled(true);
454 remote.setSaveToRemote(true);
455 configuration.setRemote(remote);
456 testCacheConfig.setConfiguration(configuration);
457 when(mockProperties.getProperty(CacheConfigImpl.SAVE_NON_OVERRIDEABLE_NAME))
458 .thenReturn("true");
459
460 assertEquals(CacheState.INITIALIZED, testObject.initialize());
461 assertDefaults(
462 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
463 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())),
464 Pair.of("isSaveToRemote", () -> assertTrue(testObject.isSaveToRemote())),
465 Pair.of("isSaveToRemoteFinal", () -> assertTrue(testObject.isSaveToRemoteFinal())));
466 }
467
468 @Test
469 void testRemoveSaveFinalIgnoredWhenRemoteSaveDisabled() {
470 Configuration configuration = new Configuration();
471 Remote remote = new Remote();
472 remote.setUrl("dummy.url.xyz");
473 remote.setEnabled(true);
474 configuration.setRemote(remote);
475 testCacheConfig.setConfiguration(configuration);
476 when(mockProperties.getProperty(CacheConfigImpl.SAVE_NON_OVERRIDEABLE_NAME))
477 .thenReturn("true");
478
479 assertEquals(CacheState.INITIALIZED, testObject.initialize());
480 assertDefaults(
481 Pair.of("getUrl", () -> assertEquals("dummy.url.xyz", testObject.getUrl())),
482 Pair.of("isRemoteCacheEnabled", () -> assertTrue(testObject.isRemoteCacheEnabled())));
483 }
484 }