1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.toolchain.building;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Properties;
27
28 import org.apache.maven.building.StringSource;
29 import org.apache.maven.toolchain.io.DefaultToolchainsReader;
30 import org.apache.maven.toolchain.io.DefaultToolchainsWriter;
31 import org.apache.maven.toolchain.io.ToolchainsParseException;
32 import org.apache.maven.toolchain.model.PersistedToolchains;
33 import org.apache.maven.toolchain.model.ToolchainModel;
34 import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
35 import org.codehaus.plexus.util.xml.Xpp3Dom;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38 import org.mockito.ArgumentMatchers;
39 import org.mockito.InjectMocks;
40 import org.mockito.MockitoAnnotations;
41 import org.mockito.Spy;
42
43 import static org.junit.jupiter.api.Assertions.assertEquals;
44 import static org.junit.jupiter.api.Assertions.assertNotNull;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.Mockito.doReturn;
47 import static org.mockito.Mockito.doThrow;
48
49 class DefaultToolchainsBuilderTest {
50 private static final String LS = System.lineSeparator();
51
52 @Spy
53 private DefaultToolchainsReader toolchainsReader;
54
55 @Spy
56 private DefaultToolchainsWriter toolchainsWriter;
57
58 @InjectMocks
59 private DefaultToolchainsBuilder toolchainBuilder;
60
61 @BeforeEach
62 void onSetup() {
63 MockitoAnnotations.initMocks(this);
64
65 Map<String, String> envVarMap = new HashMap<>();
66 envVarMap.put("testKey", "testValue");
67 envVarMap.put("testSpecialCharactersKey", "<test&Value>");
68 OperatingSystemUtils.setEnvVarSource(new TestEnvVarSource(envVarMap));
69 }
70
71 @Test
72 void testBuildEmptyRequest() throws Exception {
73 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
74 ToolchainsBuildingResult result = toolchainBuilder.build(request);
75 assertNotNull(result.getEffectiveToolchains());
76 assertNotNull(result.getProblems());
77 assertEquals(0, result.getProblems().size());
78 }
79
80 @Test
81 void testBuildRequestWithUserToolchains() throws Exception {
82 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
83 request.setUserToolchainsSource(new StringSource(""));
84
85 Properties props = new Properties();
86 props.put("key", "user_value");
87 ToolchainModel toolchain = new ToolchainModel();
88 toolchain.setType("TYPE");
89 toolchain.setProvides(props);
90 PersistedToolchains userResult = new PersistedToolchains();
91 userResult.setToolchains(Collections.singletonList(toolchain));
92 doReturn(userResult)
93 .when(toolchainsReader)
94 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
95
96 ToolchainsBuildingResult result = toolchainBuilder.build(request);
97 assertNotNull(result.getEffectiveToolchains());
98 assertEquals(1, result.getEffectiveToolchains().getToolchains().size());
99 assertEquals(
100 "TYPE", result.getEffectiveToolchains().getToolchains().get(0).getType());
101 assertEquals(
102 "user_value",
103 result.getEffectiveToolchains()
104 .getToolchains()
105 .get(0)
106 .getProvides()
107 .get("key"));
108 assertNotNull(result.getProblems());
109 assertEquals(0, result.getProblems().size());
110 }
111
112 @Test
113 void testBuildRequestWithGlobalToolchains() throws Exception {
114 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
115 request.setGlobalToolchainsSource(new StringSource(""));
116
117 Properties props = new Properties();
118 props.put("key", "global_value");
119 ToolchainModel toolchain = new ToolchainModel();
120 toolchain.setType("TYPE");
121 toolchain.setProvides(props);
122 PersistedToolchains globalResult = new PersistedToolchains();
123 globalResult.setToolchains(Collections.singletonList(toolchain));
124 doReturn(globalResult)
125 .when(toolchainsReader)
126 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
127
128 ToolchainsBuildingResult result = toolchainBuilder.build(request);
129 assertNotNull(result.getEffectiveToolchains());
130 assertEquals(1, result.getEffectiveToolchains().getToolchains().size());
131 assertEquals(
132 "TYPE", result.getEffectiveToolchains().getToolchains().get(0).getType());
133 assertEquals(
134 "global_value",
135 result.getEffectiveToolchains()
136 .getToolchains()
137 .get(0)
138 .getProvides()
139 .get("key"));
140 assertNotNull(result.getProblems());
141 assertEquals(0, result.getProblems().size());
142 }
143
144 @Test
145 void testBuildRequestWithBothToolchains() throws Exception {
146 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
147 request.setGlobalToolchainsSource(new StringSource(""));
148 request.setUserToolchainsSource(new StringSource(""));
149
150 Properties props = new Properties();
151 props.put("key", "user_value");
152 ToolchainModel toolchain = new ToolchainModel();
153 toolchain.setType("TYPE");
154 toolchain.setProvides(props);
155 PersistedToolchains userResult = new PersistedToolchains();
156 userResult.setToolchains(Collections.singletonList(toolchain));
157
158 props = new Properties();
159 props.put("key", "global_value");
160 toolchain = new ToolchainModel();
161 toolchain.setType("TYPE");
162 toolchain.setProvides(props);
163 PersistedToolchains globalResult = new PersistedToolchains();
164 globalResult.setToolchains(Collections.singletonList(toolchain));
165
166 doReturn(globalResult)
167 .doReturn(userResult)
168 .when(toolchainsReader)
169 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
170
171 ToolchainsBuildingResult result = toolchainBuilder.build(request);
172 assertNotNull(result.getEffectiveToolchains());
173 assertEquals(2, result.getEffectiveToolchains().getToolchains().size());
174 assertEquals(
175 "TYPE", result.getEffectiveToolchains().getToolchains().get(0).getType());
176 assertEquals(
177 "user_value",
178 result.getEffectiveToolchains()
179 .getToolchains()
180 .get(0)
181 .getProvides()
182 .get("key"));
183 assertEquals(
184 "TYPE", result.getEffectiveToolchains().getToolchains().get(1).getType());
185 assertEquals(
186 "global_value",
187 result.getEffectiveToolchains()
188 .getToolchains()
189 .get(1)
190 .getProvides()
191 .get("key"));
192 assertNotNull(result.getProblems());
193 assertEquals(0, result.getProblems().size());
194 }
195
196 @Test
197 void testStrictToolchainsParseException() throws Exception {
198 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
199 request.setGlobalToolchainsSource(new StringSource(""));
200 ToolchainsParseException parseException = new ToolchainsParseException("MESSAGE", 4, 2);
201 doThrow(parseException)
202 .when(toolchainsReader)
203 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
204
205 try {
206 toolchainBuilder.build(request);
207 } catch (ToolchainsBuildingException e) {
208 assertEquals(
209 "1 problem was encountered while building the effective toolchains" + LS
210 + "[FATAL] Non-parseable toolchains (memory): MESSAGE @ line 4, column 2" + LS,
211 e.getMessage());
212 }
213 }
214
215 @Test
216 void testIOException() throws Exception {
217 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
218 request.setGlobalToolchainsSource(new StringSource("", "LOCATION"));
219 IOException ioException = new IOException("MESSAGE");
220 doThrow(ioException)
221 .when(toolchainsReader)
222 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
223
224 try {
225 toolchainBuilder.build(request);
226 } catch (ToolchainsBuildingException e) {
227 assertEquals(
228 "1 problem was encountered while building the effective toolchains" + LS
229 + "[FATAL] Non-readable toolchains LOCATION: MESSAGE" + LS,
230 e.getMessage());
231 }
232 }
233
234 @Test
235 void testEnvironmentVariablesAreInterpolated() throws Exception {
236 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
237 request.setUserToolchainsSource(new StringSource(""));
238
239 Properties props = new Properties();
240 props.put("key", "${env.testKey}");
241 Xpp3Dom configurationChild = new Xpp3Dom("jdkHome");
242 configurationChild.setValue("${env.testKey}");
243 Xpp3Dom configuration = new Xpp3Dom("configuration");
244 configuration.addChild(configurationChild);
245 ToolchainModel toolchain = new ToolchainModel();
246 toolchain.setType("TYPE");
247 toolchain.setProvides(props);
248 toolchain.setConfiguration(configuration);
249 PersistedToolchains persistedToolchains = new PersistedToolchains();
250 persistedToolchains.setToolchains(Collections.singletonList(toolchain));
251
252 doReturn(persistedToolchains)
253 .when(toolchainsReader)
254 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
255
256 ToolchainsBuildingResult result = toolchainBuilder.build(request);
257 String interpolatedValue = "testValue";
258 assertEquals(
259 interpolatedValue,
260 result.getEffectiveToolchains()
261 .getToolchains()
262 .get(0)
263 .getProvides()
264 .get("key"));
265 org.codehaus.plexus.util.xml.Xpp3Dom toolchainConfiguration = (org.codehaus.plexus.util.xml.Xpp3Dom)
266 result.getEffectiveToolchains().getToolchains().get(0).getConfiguration();
267 assertEquals(
268 interpolatedValue, toolchainConfiguration.getChild("jdkHome").getValue());
269 assertNotNull(result.getProblems());
270 assertEquals(0, result.getProblems().size());
271 }
272
273 @Test
274 void testNonExistingEnvironmentVariablesAreNotInterpolated() throws Exception {
275 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
276 request.setUserToolchainsSource(new StringSource(""));
277
278 Properties props = new Properties();
279 props.put("key", "${env.testNonExistingKey}");
280 ToolchainModel toolchain = new ToolchainModel();
281 toolchain.setType("TYPE");
282 toolchain.setProvides(props);
283 PersistedToolchains persistedToolchains = new PersistedToolchains();
284 persistedToolchains.setToolchains(Collections.singletonList(toolchain));
285
286 doReturn(persistedToolchains)
287 .when(toolchainsReader)
288 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
289
290 ToolchainsBuildingResult result = toolchainBuilder.build(request);
291 assertEquals(
292 "${env.testNonExistingKey}",
293 result.getEffectiveToolchains()
294 .getToolchains()
295 .get(0)
296 .getProvides()
297 .get("key"));
298 assertNotNull(result.getProblems());
299 assertEquals(0, result.getProblems().size());
300 }
301
302 @Test
303 void testEnvironmentVariablesWithSpecialCharactersAreInterpolated() throws Exception {
304 ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
305 request.setUserToolchainsSource(new StringSource(""));
306
307 Properties props = new Properties();
308 props.put("key", "${env.testSpecialCharactersKey}");
309 ToolchainModel toolchain = new ToolchainModel();
310 toolchain.setType("TYPE");
311 toolchain.setProvides(props);
312 PersistedToolchains persistedToolchains = new PersistedToolchains();
313 persistedToolchains.setToolchains(Collections.singletonList(toolchain));
314
315 doReturn(persistedToolchains)
316 .when(toolchainsReader)
317 .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
318
319 ToolchainsBuildingResult result = toolchainBuilder.build(request);
320 String interpolatedValue = "<test&Value>";
321 assertEquals(
322 interpolatedValue,
323 result.getEffectiveToolchains()
324 .getToolchains()
325 .get(0)
326 .getProvides()
327 .get("key"));
328 assertNotNull(result.getProblems());
329 assertEquals(0, result.getProblems().size());
330 }
331
332 static class TestEnvVarSource implements OperatingSystemUtils.EnvVarSource {
333 private final Map<String, String> envVarMap;
334
335 TestEnvVarSource(Map<String, String> envVarMap) {
336 this.envVarMap = envVarMap;
337 }
338
339 public Map<String, String> getEnvMap() {
340 return envVarMap;
341 }
342 }
343 }