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.shared.invoker;
20  
21  import java.io.File;
22  import java.net.URI;
23  import java.net.URISyntaxException;
24  import java.net.URL;
25  import java.util.Arrays;
26  import java.util.Properties;
27  
28  import org.apache.maven.shared.utils.Os;
29  import org.apache.maven.shared.utils.StringUtils;
30  import org.junit.jupiter.api.BeforeEach;
31  import org.junit.jupiter.api.Test;
32  import org.junit.jupiter.api.condition.DisabledOnOs;
33  import org.junit.jupiter.api.condition.OS;
34  
35  import static org.junit.jupiter.api.Assertions.assertEquals;
36  import static org.junit.jupiter.api.Assertions.assertFalse;
37  import static org.junit.jupiter.api.Assertions.assertTrue;
38  
39  class DefaultInvokerTest {
40  
41      private Invoker invoker = newInvoker();
42      private InvocationRequest request = new DefaultInvocationRequest();
43  
44      @BeforeEach
45      public void setUp() {
46          request.setDebug(true);
47          request.setProperties(getProperties());
48          request.setBatchMode(true);
49      }
50  
51      @Test
52      @SuppressWarnings("deprecation")
53      void testBuildShouldSucceed() throws MavenInvocationException, URISyntaxException {
54          File basedir = getBasedirForBuild();
55          request.setBaseDirectory(basedir);
56          request.setGoals(Arrays.asList("clean", "package"));
57  
58          InvocationResult result = invoker.execute(request);
59  
60          assertEquals(0, result.getExitCode());
61      }
62  
63      @Test
64      void testBuildShouldFail() throws MavenInvocationException, URISyntaxException {
65          File basedir = getBasedirForBuild();
66          request.setBaseDirectory(basedir);
67          request.addArgs(Arrays.asList("clean", "package"));
68  
69          InvocationResult result = invoker.execute(request);
70  
71          assertEquals(1, result.getExitCode());
72      }
73  
74      @Test
75      void testBuildShouldTimeout() throws MavenInvocationException, URISyntaxException {
76          File basedir = getBasedirForBuild();
77          request.setBaseDirectory(basedir);
78          request.addArgs(Arrays.asList("clean", "package"));
79          request.setTimeoutInSeconds(4);
80  
81          InvocationResult result = invoker.execute(request);
82  
83          // We check the exception to be sure the failure is based on timeout.
84          assertTrue(result.getExecutionException().getMessage().contains("timed out"));
85  
86          // WARN - Windows issue MSHARED-867 - Maven and child surefire test process stays alive on Windows
87          // workaround implemented in this test to timeout test after 15 sec
88          // please also check timeout logic in maven-shared-utils
89  
90          // exitCode can't be used because in case of a timeout it's not correctly
91          // set in DefaultInvoker. Need to think about this.
92          // assertEquals( 1, result.getExitCode() );
93      }
94  
95      @Test
96      void testSpacePom() throws Exception {
97          File basedir = getBasedirForBuild();
98          request.setBaseDirectory(basedir);
99          request.setPomFileName("pom with spaces.xml");
100         request.addArg("clean");
101 
102         InvocationResult result = invoker.execute(request);
103 
104         assertEquals(0, result.getExitCode());
105     }
106 
107     @Test
108     void testSpaceAndSpecialCharPom() throws Exception {
109         File basedir = getBasedirForBuild();
110         request.setBaseDirectory(basedir);
111         request.setPomFileName("pom with spaces & special char.xml");
112         request.addArg("clean");
113 
114         InvocationResult result = invoker.execute(request);
115 
116         assertEquals(0, result.getExitCode());
117     }
118 
119     @Test
120     void testSpaceSettings() throws Exception {
121         File basedir = getBasedirForBuild();
122         request.setBaseDirectory(basedir);
123         request.setUserSettingsFile(new File(basedir, "settings with spaces.xml"));
124         request.addArg("validate");
125 
126         InvocationResult result = invoker.execute(request);
127 
128         assertEquals(0, result.getExitCode());
129     }
130 
131     @Test
132     void testSpaceLocalRepo() throws Exception {
133         File basedir = getBasedirForBuild();
134         request.setBaseDirectory(basedir);
135         request.setLocalRepositoryDirectory(new File(basedir, "repo with spaces"));
136         request.addArg("validate");
137 
138         InvocationResult result = invoker.execute(request);
139 
140         assertEquals(0, result.getExitCode());
141     }
142 
143     @Test
144     void testSpaceProperties() throws Exception {
145         File basedir = getBasedirForBuild();
146         request.setBaseDirectory(basedir);
147         Properties props = getProperties();
148         props.setProperty("key", "value with spaces");
149         props.setProperty("key with spaces", "value");
150         request.setProperties(props);
151         request.addArg("validate");
152 
153         InvocationResult result = invoker.execute(request);
154 
155         assertEquals(0, result.getExitCode());
156     }
157 
158     @Test
159     void testPomOutsideProject() throws Exception {
160         File basedir = getBasedirForBuild();
161         request.setBaseDirectory(basedir);
162         File pom = new File(basedir, "temp/pom.xml");
163         request.setPomFile(pom);
164         request.addArg("validate");
165 
166         InvocationResult result = invoker.execute(request);
167 
168         assertEquals(0, result.getExitCode());
169     }
170 
171     @Test
172     void testMavenWrapperInProject() throws Exception {
173         File basedir = getBasedirForBuild();
174         request.setBaseDirectory(basedir);
175         request.addArg("test-wrapper-goal");
176         request.setMavenExecutable(new File("./mvnw"));
177 
178         final StringBuilder outlines = new StringBuilder();
179         request.setOutputHandler(outlines::append);
180 
181         InvocationResult result = invoker.execute(request);
182 
183         assertEquals(0, result.getExitCode());
184         if (Os.isFamily(Os.FAMILY_WINDOWS)) {
185             assertEquals("Windows Wrapper executed", outlines.toString());
186         } else {
187             assertEquals("Unix Wrapper executed", outlines.toString());
188         }
189     }
190 
191     @Test
192     @DisabledOnOs(OS.WINDOWS) // mvn 3.6.3 and windows ...
193     void notInheritEnvVariables() throws Exception {
194 
195         // ensure that we have env variable in current process
196         assertEquals("test-env-value", System.getenv("INVOKER_TEST_ENV_1"));
197 
198         File basedir = getBasedirForBuild();
199         request.setBaseDirectory(basedir);
200         request.addArg("initialize");
201         request.setShellEnvironmentInherited(false);
202         request.addShellEnvironment("INVOKER_TEST_ENV_2", "test-env-value-2");
203         // Maven 3.6.3 required JAVA_HOME
204         request.addShellEnvironment("JAVA_HOME", System.getProperty("java.home"));
205 
206         final StringBuilder outlines = new StringBuilder();
207         request.setOutputHandler(line -> outlines.append(line).append(System.lineSeparator()));
208 
209         InvocationResult result = invoker.execute(request);
210 
211         String output = outlines.toString();
212         assertEquals(
213                 0,
214                 result.getExitCode(),
215                 () -> "Maven exit code: " + result.getExitCode() + System.lineSeparator() + output.trim());
216         assertFalse(output.contains("INVOKER_TEST_ENV_1"));
217         assertTrue(output.contains("INVOKER_TEST_ENV_2=test-env-value-2"));
218     }
219 
220     private Invoker newInvoker() {
221         Invoker invoker = new DefaultInvoker();
222 
223         invoker.setMavenHome(findMavenHome());
224 
225         InvokerLogger logger = new SystemOutLogger();
226         logger.setThreshold(InvokerLogger.DEBUG);
227         invoker.setLogger(logger);
228 
229         invoker.setLocalRepositoryDirectory(findLocalRepo());
230 
231         return invoker;
232     }
233 
234     private File findMavenHome() {
235         String mavenHome = System.getProperty("maven.home");
236 
237         if (mavenHome == null) {
238             throw new IllegalStateException(
239                     "Cannot find Maven application " + "directory. Specify 'maven.home' system property");
240         }
241 
242         return new File(mavenHome);
243     }
244 
245     private File findLocalRepo() {
246         String basedir = System.getProperty("maven.repo.local", "");
247 
248         if (basedir != null && !basedir.isEmpty()) {
249             return new File(basedir);
250         }
251 
252         return null;
253     }
254 
255     private File getBasedirForBuild() throws URISyntaxException {
256         StackTraceElement element = new NullPointerException().getStackTrace()[1];
257         String methodName = element.getMethodName();
258 
259         String dirName = StringUtils.addAndDeHump(methodName);
260 
261         ClassLoader cloader = Thread.currentThread().getContextClassLoader();
262         URL dirResource = cloader.getResource(dirName);
263 
264         if (dirResource == null) {
265             throw new IllegalStateException("Project: " + dirName + " for test method: " + methodName + " is missing.");
266         }
267 
268         return new File(new URI(dirResource.toString()).getPath());
269     }
270 
271     private Properties getProperties() {
272         Properties properties = new Properties();
273         properties.put("maven.compiler.source", "1.8");
274         properties.put("maven.compiler.target", "1.8");
275 
276         String httpProtocols = System.getProperty("https.protocols");
277         if (httpProtocols != null) {
278             properties.put("https.protocols", httpProtocols);
279         }
280         return properties;
281     }
282 }