From 8fca68bda7f8d16411c4857c95435d348ae77324 Mon Sep 17 00:00:00 2001 From: Simon Urli Date: Tue, 20 Mar 2018 17:33:51 +0100 Subject: [PATCH] Improve DefaultInvoker with a timeout. Add corresponding test. This aims at fixing MINVOKER-233 --- .../maven/shared/invoker/DefaultInvoker.java | 19 ++++-- .../apache/maven/shared/invoker/Invoker.java | 13 ++++ .../shared/invoker/DefaultInvokerTest.java | 26 ++++++++ .../test-build-should-timeout/pom.xml | 34 +++++++++++ .../org/apache/maven/shared/invoker/App.java | 32 ++++++++++ .../apache/maven/shared/invoker/AppTest.java | 61 +++++++++++++++++++ 6 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 src/test/resources/test-build-should-timeout/pom.xml create mode 100644 src/test/resources/test-build-should-timeout/src/main/java/org/apache/maven/shared/invoker/App.java create mode 100644 src/test/resources/test-build-should-timeout/src/test/java/org/apache/maven/shared/invoker/AppTest.java diff --git a/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java b/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java index 39be540..3ef26c3 100644 --- a/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java +++ b/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java @@ -39,6 +39,8 @@ public class DefaultInvoker public static final String ROLE_HINT = "default"; + private static final int NO_TIMEOUT = 0; + private static final InvokerLogger DEFAULT_LOGGER = new SystemOutLogger(); private static final InvocationOutputHandler DEFAULT_OUTPUT_HANDLER = new SystemOutHandler(); @@ -60,6 +62,12 @@ public class DefaultInvoker private InvocationOutputHandler errorHandler = DEFAULT_OUTPUT_HANDLER; public InvocationResult execute( InvocationRequest request ) + throws MavenInvocationException + { + return this.execute( request , NO_TIMEOUT ); + } + + public InvocationResult execute( InvocationRequest request, int timeoutInSeconds ) throws MavenInvocationException { MavenCommandLineBuilder cliBuilder = new MavenCommandLineBuilder(); @@ -108,7 +116,7 @@ public InvocationResult execute( InvocationRequest request ) try { - int exitCode = executeCommandLine( cli, request ); + int exitCode = executeCommandLine( cli, request, timeoutInSeconds ); result.setExitCode( exitCode ); } @@ -120,7 +128,7 @@ public InvocationResult execute( InvocationRequest request ) return result; } - private int executeCommandLine( Commandline cli, InvocationRequest request ) + private int executeCommandLine( Commandline cli, InvocationRequest request, int timeoutInSeconds ) throws CommandLineException { int result = Integer.MIN_VALUE; @@ -141,7 +149,7 @@ private int executeCommandLine( Commandline cli, InvocationRequest request ) getLogger().info( "Executing in batch mode. The configured input stream will be ignored." ); } - result = CommandLineUtils.executeCommandLine( cli, outputHandler, errorHandler ); + result = CommandLineUtils.executeCommandLine( cli, outputHandler, errorHandler, timeoutInSeconds ); } else { @@ -150,11 +158,12 @@ private int executeCommandLine( Commandline cli, InvocationRequest request ) getLogger().warn( "Maven will be executed in interactive mode" + ", but no input stream has been configured for this MavenInvoker instance." ); - result = CommandLineUtils.executeCommandLine( cli, outputHandler, errorHandler ); + result = CommandLineUtils.executeCommandLine( cli, outputHandler, errorHandler, timeoutInSeconds ); } else { - result = CommandLineUtils.executeCommandLine( cli, inputStream, outputHandler, errorHandler ); + result = CommandLineUtils.executeCommandLine( cli, inputStream, outputHandler, errorHandler, + timeoutInSeconds ); } } diff --git a/src/main/java/org/apache/maven/shared/invoker/Invoker.java b/src/main/java/org/apache/maven/shared/invoker/Invoker.java index 580e7b3..10574f6 100644 --- a/src/main/java/org/apache/maven/shared/invoker/Invoker.java +++ b/src/main/java/org/apache/maven/shared/invoker/Invoker.java @@ -47,6 +47,19 @@ public interface Invoker InvocationResult execute( InvocationRequest request ) throws MavenInvocationException; + /** + * Executes Maven using the parameters specified by the given invocation request. Parameters not specified by the + * invocation request will be derived from the state of this invoker instance. In case both the invoker instance and + * the invocation request provide a value for a particular option, the value from the invocation request dominates. + * + * @param request The invocation request to execute, must not be null. + * @param timeoutInSeconds If a value > 0 is specified, the goal might be interrupted after the timeout is reached. + * @return The result of the Maven invocation, never null. + * @throws MavenInvocationException + */ + InvocationResult execute( InvocationRequest request, int timeoutInSeconds ) + throws MavenInvocationException; + /** * Gets the path to the base directory of the local repository to use for the Maven invocation. * diff --git a/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java b/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java index 02084ae..00c4abb 100644 --- a/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java +++ b/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java @@ -87,6 +87,32 @@ public void testBuildShouldFail() assertEquals( 1, result.getExitCode() ); } + @Test + public void testBuildShouldTimeout() + throws IOException, MavenInvocationException, URISyntaxException + { + File basedir = getBasedirForBuild(); + + Invoker invoker = newInvoker(); + + InvocationRequest request = new DefaultInvocationRequest(); + request.setBaseDirectory( basedir ); + request.setDebug( true ); + request.setGoals( Arrays.asList( "clean", "package" ) ); + + if ( !System.getProperty( "java.version" ).startsWith( "1." ) ) + { + Properties properties = new Properties(); + properties.put( "maven.compiler.source", "1.6" ); + properties.put( "maven.compiler.target", "1.6" ); + request.setProperties( properties ); + } + + InvocationResult result = invoker.execute( request, 10 ); + + assertEquals( 1, result.getExitCode() ); + } + @Test public void testSpacePom() throws Exception diff --git a/src/test/resources/test-build-should-timeout/pom.xml b/src/test/resources/test-build-should-timeout/pom.xml new file mode 100644 index 0000000..d43d9a5 --- /dev/null +++ b/src/test/resources/test-build-should-timeout/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + org.apache.maven.shared.invoker + test-build-should-timeout + jar + 1 + + + junit + junit + 3.8.2 + test + + + diff --git a/src/test/resources/test-build-should-timeout/src/main/java/org/apache/maven/shared/invoker/App.java b/src/test/resources/test-build-should-timeout/src/main/java/org/apache/maven/shared/invoker/App.java new file mode 100644 index 0000000..753a51c --- /dev/null +++ b/src/test/resources/test-build-should-timeout/src/main/java/org/apache/maven/shared/invoker/App.java @@ -0,0 +1,32 @@ +package org.apache.maven.shared.invoker; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + } +} diff --git a/src/test/resources/test-build-should-timeout/src/test/java/org/apache/maven/shared/invoker/AppTest.java b/src/test/resources/test-build-should-timeout/src/test/java/org/apache/maven/shared/invoker/AppTest.java new file mode 100644 index 0000000..3a01f8a --- /dev/null +++ b/src/test/resources/test-build-should-timeout/src/test/java/org/apache/maven/shared/invoker/AppTest.java @@ -0,0 +1,61 @@ +package org.apache.maven.shared.invoker; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Not ending test + */ + public void testApp() + { + while (true) { + Thread.sleep(1); + } + + assertTrue(true); + } +}