001package org.apache.maven.script.ant;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import static org.hamcrest.MatcherAssert.assertThat;
023import static org.junit.jupiter.api.Assertions.assertNotNull;
024import static org.junit.jupiter.api.Assertions.assertTrue;
025import static org.mockito.Mockito.atLeastOnce;
026import static org.mockito.Mockito.mock;
027import static org.mockito.Mockito.verify;
028import static org.mockito.Mockito.when;
029import static org.hamcrest.CoreMatchers.endsWith;
030import static org.hamcrest.CoreMatchers.startsWith;
031
032import java.io.ByteArrayOutputStream;
033import java.io.File;
034import java.io.IOException;
035import java.io.InputStreamReader;
036import java.io.PrintStream;
037import java.io.Reader;
038import java.net.URISyntaxException;
039import java.net.URL;
040import java.nio.file.Paths;
041import java.util.ArrayList;
042import java.util.Collections;
043import java.util.HashMap;
044import java.util.List;
045import java.util.Map;
046
047import org.apache.maven.artifact.Artifact;
048import org.apache.maven.execution.MavenSession;
049import org.apache.maven.model.Build;
050import org.apache.maven.model.Model;
051import org.apache.maven.plugin.MojoExecution;
052import org.apache.maven.plugin.MojoExecutionException;
053import org.apache.maven.plugin.descriptor.MojoDescriptor;
054import org.apache.maven.plugin.descriptor.PluginDescriptor;
055import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
056import org.apache.maven.project.MavenProject;
057import org.apache.maven.project.path.PathTranslator;
058import org.apache.tools.ant.BuildEvent;
059import org.apache.tools.ant.BuildListener;
060import org.codehaus.plexus.archiver.ArchiverException;
061import org.codehaus.plexus.archiver.jar.JarArchiver;
062import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
063import org.codehaus.plexus.component.factory.ComponentInstantiationException;
064import org.codehaus.plexus.component.factory.ant.AntScriptInvoker;
065import org.codehaus.plexus.component.repository.ComponentRequirement;
066import org.codehaus.plexus.configuration.PlexusConfigurationException;
067import org.codehaus.plexus.logging.Logger;
068import org.codehaus.plexus.logging.console.ConsoleLogger;
069import org.junit.jupiter.api.BeforeEach;
070import org.junit.jupiter.api.Test;
071import org.mockito.ArgumentCaptor;
072
073// at least one test class must be public for test-javadoc report
074public class AntMojoWrapperTest
075{
076    
077    private BuildListener buildListener;
078
079    @BeforeEach
080    public void setUp() 
081    {
082        buildListener = mock( BuildListener.class );
083    }
084    
085    @Test
086    void test2xStylePlugin()
087        throws PlexusConfigurationException, IOException, ComponentInstantiationException, MojoExecutionException,
088        ComponentConfigurationException, ArchiverException, URISyntaxException
089    {
090        String pluginXml = "META-INF/maven/plugin-2.1.xml";
091
092        List<String> messages = run( pluginXml );
093
094        assertPresence( messages, "Unpacked Ant build scripts (in Maven build directory)." );
095        assertPresence( messages, "Maven parameter expression evaluator for Ant properties." );
096        assertPresence( messages, "Maven standard project-based classpath references." );
097        assertPresence( messages, "Maven standard plugin-based classpath references." );
098        assertPresence( messages, "Maven project, session, mojo-execution, or path-translation parameter information is" );
099        assertPresence( messages, "maven-script-ant < 2.1.0, or used maven-plugin-tools-ant < 2.2 during release" );
100
101        ArgumentCaptor<BuildEvent> buildEvent = ArgumentCaptor.forClass(BuildEvent.class);
102        verify( buildListener, atLeastOnce() ).messageLogged( buildEvent.capture() );
103
104        // last message
105        assertThat( buildEvent.getValue().getMessage(), startsWith( "plugin classpath is: " ) );
106        assertThat( buildEvent.getValue().getMessage(), endsWith( ".test.jar" ) );
107    }
108
109    private void assertPresence( List<String> messages, String test )
110    {
111        assertTrue( messages.stream().noneMatch( s -> s.contains( test ) ),
112                "Test string: '" + test + "' was found in output, but SHOULD NOT BE THERE." );
113    }
114
115    private List<String> run( String pluginXml )
116        throws PlexusConfigurationException, IOException, ComponentInstantiationException, MojoExecutionException,
117        ComponentConfigurationException, ArchiverException, URISyntaxException
118    {
119        StackTraceElement stack = new Throwable().getStackTrace()[1];
120        System.out.println( "\n\nRunning: " + stack.getMethodName() + "\n\n" );
121
122        URL resource = Thread.currentThread().getContextClassLoader().getResource( pluginXml );
123
124        assertNotNull( resource, "plugin descriptor not found: '" + pluginXml + "'." );
125
126        PluginDescriptor pd;
127        try ( Reader reader = new InputStreamReader( resource.openStream() ) )
128        {
129            pd = new PluginDescriptorBuilder().build( reader, pluginXml );
130        }
131
132        Map<String, Object> config = new HashMap<>();
133        config.put( "basedir", new File( "." ).getAbsoluteFile() );
134        config.put( "messageLevel", "info" );
135
136        MojoDescriptor md = pd.getMojo( "test" );
137
138        AntMojoWrapper wrapper =
139            new AntMojoWrapper( new AntScriptInvoker( md, Thread.currentThread().getContextClassLoader() ) );
140
141        wrapper.enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) );
142
143        Artifact artifact = mock( Artifact.class );
144        PathTranslator pt = mock( PathTranslator.class );
145
146        File pluginXmlFile = Paths.get( resource.toURI() ).toFile();
147
148        File jarFile = File.createTempFile( "AntMojoWrapperTest.", ".test.jar" );
149        jarFile.deleteOnExit();
150
151        JarArchiver archiver = new JarArchiver();
152        archiver.setDestFile( jarFile );
153        archiver.addFile( pluginXmlFile, pluginXml );
154        archiver.createArchive();
155
156        when( artifact.getFile() ).thenReturn( jarFile );
157
158        Model model = new Model();
159
160        Build build = new Build();
161        build.setDirectory( "target" );
162
163        model.setBuild( build );
164
165        MavenProject project = new MavenProject( model );
166        project.setFile( new File( "pom.xml" ).getAbsoluteFile() );
167
168        pd.setPluginArtifact( artifact );
169        pd.setArtifacts( Collections.singletonList( artifact ) );
170
171        config.put( "project", project );
172        config.put( "session", new MavenSession( null, null, null, null, null, null, null, null, null, null ) );
173        config.put( "mojoExecution", new MojoExecution( md ) );
174
175        ComponentRequirement cr = new ComponentRequirement();
176        cr.setRole( PathTranslator.class.getName() );
177
178        wrapper.addComponentRequirement( cr, pt );
179
180        wrapper.setComponentConfiguration( config );
181
182        TestBuildListener tbl = new TestBuildListener();
183        
184        wrapper.getAntProject().addBuildListener( buildListener );
185        
186        PrintStream oldOut = System.out;
187        
188        ByteArrayOutputStream baos = new ByteArrayOutputStream();
189        try
190        {
191            System.setOut( new PrintStream( baos ) );
192
193            wrapper.execute();
194        }
195        finally
196        {
197            System.setOut( oldOut );
198        }
199
200        System.out.println( "\n\n" + stack.getMethodName() + " executed; verifying...\n\n" );
201
202        List<String> messages = new ArrayList<>();
203        if ( !tbl.messages.isEmpty() )
204        {
205            messages.addAll( tbl.messages );
206        }
207        
208        messages.add( baos.toString() );
209        
210        return messages;
211    }
212
213    private static final class TestBuildListener
214        implements BuildListener
215    {
216        private final List<String> messages = new ArrayList<>();
217
218        public void buildFinished( BuildEvent arg0 )
219        {
220        }
221
222        public void buildStarted( BuildEvent arg0 )
223        {
224        }
225
226        public void messageLogged( BuildEvent event )
227        {
228            messages.add( event.getMessage() );
229        }
230
231        public void targetFinished( BuildEvent arg0 )
232        {
233        }
234
235        public void targetStarted( BuildEvent arg0 )
236        {
237        }
238
239        public void taskFinished( BuildEvent arg0 )
240        {
241        }
242
243        public void taskStarted( BuildEvent arg0 )
244        {
245        }
246    }
247}