View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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 }