001    package org.codehaus.mojo.exec;
002    
003    /*
004     * Copyright 2005-2006 The Codehaus.
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *      http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    import org.apache.maven.artifact.repository.ArtifactRepository;
020    import org.apache.maven.artifact.repository.DefaultArtifactRepository;
021    import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
022    import org.apache.maven.plugin.MojoExecutionException;
023    import org.apache.maven.plugin.AbstractMojo;
024    import org.apache.maven.plugin.testing.AbstractMojoTestCase;
025    import org.apache.maven.project.MavenProject;
026    import org.apache.maven.project.MavenProjectBuilder;
027    import org.apache.maven.monitor.logging.DefaultLog;
028    import org.codehaus.plexus.util.StringOutputStream;
029    import org.codehaus.plexus.logging.Logger;
030    import org.codehaus.plexus.logging.console.ConsoleLogger;
031    
032    import java.io.File;
033    import java.io.PrintStream;
034    
035    /**
036     * @author Jerome Lacoste <jerome@coffeebreaks.org>
037     * @version $Id: ExecJavaMojoTest.java 10761 2009-09-24 09:38:21Z stephenconnolly $
038     */
039    public class ExecJavaMojoTest
040        extends AbstractMojoTestCase
041    {
042    
043        /*
044        This one won't work yet
045        public void xxtestSimpleRunPropertiesAndArguments()
046            throws MojoExecutionException, Exception
047        {
048            File pom = new File( getBasedir(), "src/test/projects/project2/pom.xml" );
049    
050            String output = execute( pom, "java" );
051    
052            System.out.println(output);
053    
054            assertEquals( -1, output.trim().indexOf( "ERROR" ) );
055        }
056        */
057    
058        /**
059         * Check that a simple execution with no arguments and no system properties produces the expected result
060         * <p/>
061         * we load the config from a pom file and fill up the MavenProject property ourselves
062         */
063        public void testSimpleRun()
064            throws Exception
065        {
066            File pom = new File( getBasedir(), "src/test/projects/project4/pom.xml" );
067    
068            String output = execute( pom, "java" );
069    
070            assertEquals( "Hello" + System.getProperty( "line.separator" ), output );
071        }
072    
073        /**
074         * MEXEC-10 Check that an execution with no arguments and an system property with no value
075         * produces the expected result
076         * <p/>
077         * we load the config from a pom file and fill up the MavenProject property ourselves
078         */
079        public void testEmptySystemProperty()
080            throws Exception
081        {
082            File pom = new File( getBasedir(), "src/test/projects/project5/pom.xml" );
083    
084            assertNull( "System property not yet created",
085                         System.getProperty( "project5.property.with.no.value" ) );
086    
087            execute( pom, "java" );
088    
089            assertEquals( "System property now empty",
090                           "",
091                           System.getProperty( "project5.property.with.no.value" ) );
092        }
093    
094        /**
095         * MEXEC-29 exec:java throws NPE if the mainClass main method has not a correct signature
096         * <p/>
097         */
098        public void testIncorrectMainMethodSignature()
099            throws Exception
100        {
101            File pom = new File( getBasedir(), "src/test/projects/project12/pom.xml" );
102    
103            try {
104                String output = execute( pom, "java" );
105            } catch (MojoExecutionException e) {
106                assertTrue( stringContains( e.getMessage(), "The specified mainClass doesn't contain a main method with appropriate signature." ) );
107            }
108    
109        }
110    
111    // this test doesn't work as the classpath passed to the project when executing the POM isn't the same as when maven is executed from within the project dir
112    // Should be moved as an integration-test
113    /*
114        public void testSetClasspathScopeToTest()
115            throws Exception
116        {
117            File pom = new File( getBasedir(), "src/test/projects/project14/pom.xml" );
118    
119            String output = execute( pom, "java" );
120    
121            assertEquals( "Hello" + System.getProperty( "line.separator" ), output );
122        }
123    */
124        
125        // java 1.4 compatibility
126        private boolean stringContains( String str, String sequence )
127        {
128            return str.indexOf( sequence ) != -1;
129        }
130    
131        /**
132         * For cases where the Java code spawns Threads and main returns soon.
133         * See <a href="http://jira.codehaus.org/browse/MEXEC-6">MEXEC-6</a>.
134         */
135        public void testWaitNoDaemonThreads()
136            throws Exception
137        {
138            File pom = new File( getBasedir(), "src/test/projects/project7/pom.xml" );
139    
140            String output = execute( pom, "java" );
141    
142            assertEquals( MainWithThreads.ALL_EXITED, output.trim() );
143        }
144    
145        /**
146         * For cases where the Java code spawns Threads and main returns soon, but code contains non interruptible threads.
147         * User is required to timeout the execution, otherwise it will hang.
148         * See <a href="http://jira.codehaus.org/browse/MEXEC-15">MEXEC-15</a>.
149         */
150        public void testWaitNonInterruptibleDaemonThreads()
151            throws Exception
152        {
153            File pom = new File( getBasedir(), "src/test/projects/project9/pom.xml" );
154    
155            String output = execute( pom, "java" );
156    
157            assertEquals( MainWithThreads.TIMER_IGNORED, output.trim() );
158        }
159    
160        /**
161         * See <a href="http://jira.codehaus.org/browse/MEXEC-15">MEXEC-15</a>.
162         * FIXME: this sometimes fail with unit.framework.ComparisonFailure: expected:<...> but was:<...3(f)>
163         */
164        public void testUncooperativeThread()
165            throws Exception
166        {
167            File pom = new File( getBasedir(), "src/test/projects/project10/pom.xml" );
168            String output = execute( pom, "java" );
169            // note: execute() will wait a little bit before returning the output,
170            // thereby allowing the stop()'ed thread to output the final "(f)".
171            assertEquals( MainUncooperative.SUCCESS, output.trim() );
172        }
173    
174        /**
175         * See <a href="http://jira.codehaus.org/browse/MEXEC-17">MEXEC-17</a>.
176         */
177        /**
178        This test doesn't work because the sun.tools.javac.Main class referenced in the
179        project pom is found even if the system scope dependencies are not added by the plugin.
180        The class was probably loaded by another plugin ?!
181    
182        To fix the test we have to:
183        - maybe use a different system scope dependency/class to load.
184        - find a different way to test.
185    
186        When ran manually, the test works though (i.e. removing the code that manually adds
187        the system scope dependencies make the test fail).
188    
189        public void testSystemDependencyFound()
190            throws Exception
191        {
192            File pom = new File( getBasedir(), "src/test/projects/project11/pom.xml" );
193    
194            String output = execute( pom, "java" );
195    
196            assertEquals( FindClassInClasspath.FOUND_ALL, output.trim() );
197        }
198        */
199    
200        /**
201         * Test the commandline parsing facilities of the {@link AbstractExecMojo} class
202         */
203        public void testRunWithArgs() throws Exception
204        {
205    
206            String resultString = execute( new File( getBasedir(), "src/test/projects/project8/pom.xml" ), "java" );
207    
208            String LS = System.getProperty("line.separator");
209            String expectedResult = "Hello" + LS + "Arg1" + LS +"Arg2a Arg2b" + LS;
210            assertEquals( expectedResult, resultString );
211        }
212    
213        /**
214         * @return output from System.out during mojo execution
215         */
216        private String execute( File pom, String goal ) throws Exception {
217    
218            ExecJavaMojo mojo;
219            mojo = (ExecJavaMojo) lookupMojo( goal, pom );
220    
221            setUpProject( pom, mojo );
222    
223            MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );
224    
225            // why isn't this set up by the harness based on the default-value?  TODO get to bottom of this!
226            setVariableValueToObject( mojo, "includeProjectDependencies", Boolean.TRUE );
227            setVariableValueToObject( mojo, "killAfter", new Long( -1 ) );
228            setVariableValueToObject( mojo, "cleanupDaemonThreads", Boolean.TRUE );
229            setVariableValueToObject( mojo, "classpathScope", "compile" );
230    
231            assertNotNull( mojo );
232            assertNotNull( project );
233    
234            // trap System.out
235            PrintStream out = System.out;
236            StringOutputStream stringOutputStream = new StringOutputStream();
237            System.setOut( new PrintStream( stringOutputStream ) );
238            // ensure we don't log unnecessary stuff which would interfere with assessing success of tests
239            mojo.setLog( new DefaultLog( new ConsoleLogger( Logger.LEVEL_ERROR, "exec:java" ) ) );
240    
241            try
242            {
243                mojo.execute();
244            }
245            finally
246            {
247                // see testUncooperativeThread() for explaination
248                Thread.sleep( 300 ); // time seems about right
249                System.setOut( out );
250            }
251    
252            return stringOutputStream.toString();
253        }
254    
255        private void setUpProject( File pomFile, AbstractMojo mojo )
256            throws Exception
257        {
258            MavenProjectBuilder builder = (MavenProjectBuilder) lookup( MavenProjectBuilder.ROLE );
259    
260            ArtifactRepositoryLayout localRepositoryLayout =
261                (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, "default" );
262    
263            String path = "src/test/repository";
264    
265            ArtifactRepository localRepository = new DefaultArtifactRepository( "local", "file://" +
266                new File( path ).getAbsolutePath(), localRepositoryLayout );
267    
268            MavenProject project = builder.buildWithDependencies( pomFile, localRepository, null );
269            // this gets the classes for these tests of this mojo (exec plugin) onto the project classpath for the test
270            project.getBuild().setOutputDirectory( new File( "target/test-classes" ).getAbsolutePath() );
271            setVariableValueToObject( mojo, "project", project );
272        }
273    }