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