001package org.apache.maven.scm;
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 org.apache.maven.scm.manager.ScmManager;
023import org.apache.maven.scm.repository.ScmRepository;
024import org.codehaus.plexus.ContainerConfiguration;
025import org.codehaus.plexus.PlexusConstants;
026import org.codehaus.plexus.util.FileUtils;
027import org.codehaus.plexus.util.StringUtils;
028import org.codehaus.plexus.util.cli.CommandLineUtils;
029import org.codehaus.plexus.util.cli.CommandLineUtils.StringStreamConsumer;
030import org.codehaus.plexus.util.cli.Commandline;
031import org.junit.Before;
032
033import java.io.File;
034import java.io.FileWriter;
035import java.io.IOException;
036import java.util.Calendar;
037import java.util.Date;
038import java.util.TimeZone;
039
040import static org.junit.Assert.assertEquals;
041import static org.junit.Assert.assertFalse;
042import static org.junit.Assert.assertTrue;
043import static org.junit.Assert.fail;
044import static org.junit.Assume.assumeTrue;
045
046/**
047 * Base class for all SCM tests. Consumers will typically
048 * extend this class while tck test would extend ScmTckTestCase.
049 * <br>
050 * This class basically defines default locations for the
051 * test environment and implements convenience methods.
052 *
053 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
054 *
055 */
056public abstract class ScmTestCase
057    extends PlexusJUnit4TestSupport
058{
059    protected static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone( "GMT" );
060
061    private static boolean debugExecute;
062
063    private ScmManager scmManager;
064
065    @Before
066    @Override
067    public void setUp()
068        throws Exception
069    {
070        super.setUp();
071
072        deleteDirectory( getRepositoryRoot() );
073        assertFalse( getRepositoryRoot().exists() );
074        deleteDirectory( getWorkingCopy() );
075        assertFalse( getWorkingCopy().exists() );
076        deleteDirectory( getWorkingDirectory() );
077        assertFalse( getWorkingDirectory().exists() );
078        deleteDirectory( getAssertionCopy() );
079        assertFalse( getAssertionCopy().exists() );
080        deleteDirectory( getUpdatingCopy() );
081        assertFalse( getUpdatingCopy().exists() );
082
083        scmManager = null;
084    }
085
086    @Override
087    protected void customizeContainerConfiguration( final ContainerConfiguration configuration )
088    {
089        configuration.setClassPathScanning( PlexusConstants.SCANNING_INDEX ).setAutoWiring( true );
090    }
091
092    /**
093     * @return default location of the test read/write repository
094     */
095    protected File getRepositoryRoot()
096    {
097        return PlexusJUnit4TestSupport.getTestFile( "target/scm-test/repository" );
098    }
099
100    /**
101     * @return Location of the revisioned (read only) repository
102     */
103    protected File getRepository()
104    {
105        return PlexusJUnit4TestSupport.getTestFile( "/src/test/repository" );
106    }
107
108    /**
109     * @return location of the working copy (always checkout)
110     */
111    protected File getWorkingCopy()
112    {
113        return PlexusJUnit4TestSupport.getTestFile( "target/scm-test/working-copy" );
114    }
115
116    /**
117     * Legacy method - same as getWorkingCopy()
118     *
119     * @return location of the working copy (always checkout)
120     */
121    protected File getWorkingDirectory()
122    {
123        return getWorkingCopy();
124    }
125
126    /**
127     * @return default location for doing assertions on a working tree
128     */
129    protected File getAssertionCopy()
130    {
131        return PlexusJUnit4TestSupport.getTestFile( "target/scm-test/assertion-copy" );
132    }
133
134    /**
135     * @return default location for doing update operations on a working tree
136     */
137    protected File getUpdatingCopy()
138    {
139        return PlexusJUnit4TestSupport.getTestFile( "target/scm-test/updating-copy" );
140    }
141
142    protected ScmManager getScmManager()
143        throws Exception
144    {
145        if ( scmManager == null )
146        {
147            scmManager = lookup( ScmManager.class );
148        }
149
150        return scmManager;
151    }
152
153    protected ScmRepository makeScmRepository( String scmUrl )
154        throws Exception
155    {
156        return getScmManager().makeScmRepository( scmUrl );
157    }
158
159    public void assertPath( String expectedPath, String actualPath )
160        throws Exception
161    {
162        assertEquals( expectedPath.replace( '\\', '/' ), actualPath.replace( '\\', '/' ) );
163    }
164
165    protected void assertFile( File root, String fileName )
166        throws Exception
167    {
168        File file = new File( root, fileName );
169
170        assertTrue( "Missing file: '" + file.getAbsolutePath() + "'.", file.exists() );
171
172        assertTrue( "File isn't a file: '" + file.getAbsolutePath() + "'.", file.isFile() );
173
174        String expected = fileName;
175
176        String actual = FileUtils.fileRead( file );
177
178        assertEquals( "The file doesn't contain the expected contents. File: " + file.getAbsolutePath(), expected,
179                      actual );
180    }
181
182    protected void assertResultIsSuccess( ScmResult result )
183    {
184        if ( result.isSuccess() )
185        {
186            return;
187        }
188
189        printOutputError( result );
190
191        fail( "The command result success flag was false." );
192    }
193
194    protected void printOutputError( ScmResult result )
195    {
196        System.err.println( "----------------------------------------------------------------------" );
197        System.err.println( "Provider message" );
198        System.err.println( "----------------------------------------------------------------------" );
199        System.err.println( result.getProviderMessage() );
200        System.err.println( "----------------------------------------------------------------------" );
201
202        System.err.println( "----------------------------------------------------------------------" );
203        System.err.println( "Command output" );
204        System.err.println( "----------------------------------------------------------------------" );
205        System.err.println( result.getCommandOutput() );
206        System.err.println( "----------------------------------------------------------------------" );
207    }
208
209    protected ScmFileSet getScmFileSet()
210    {
211        return new ScmFileSet( getWorkingCopy() );
212    }
213
214    protected static void setDebugExecute( boolean debugExecute )
215    {
216        ScmTestCase.debugExecute = debugExecute;
217    }
218
219    /**
220     * Execute the command line
221     *
222     * @param workingDirectory not null
223     * @param executable       not null, should be a system command
224     * @param arguments        not null
225     * @throws Exception if any
226     * @see CommandLineUtils#executeCommandLine(Commandline, org.codehaus.plexus.util.cli.StreamConsumer,
227     *      org.codehaus.plexus.util.cli.StreamConsumer)
228     */
229    public static void execute( File workingDirectory, String executable, String arguments )
230        throws Exception
231    {
232        Commandline cl = new Commandline();
233
234        cl.setExecutable( executable );
235
236        cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
237
238        cl.addArguments( CommandLineUtils.translateCommandline( arguments ) );
239
240        StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
241
242        StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
243
244        System.out.println( "Test command line: " + cl );
245
246        int exitValue = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
247
248        if ( debugExecute || exitValue != 0 )
249        {
250            System.err.println( "-----------------------------------------" );
251            System.err.println( "Command line: " + cl );
252            System.err.println( "Working directory: " + cl.getWorkingDirectory() );
253            System.err.println( "-----------------------------------------" );
254            System.err.println( "Standard output: " );
255            System.err.println( "-----------------------------------------" );
256            System.err.println( stdout.getOutput() );
257            System.err.println( "-----------------------------------------" );
258
259            System.err.println( "Standard error: " );
260            System.err.println( "-----------------------------------------" );
261            System.err.println( stderr.getOutput() );
262            System.err.println( "-----------------------------------------" );
263        }
264
265        if ( exitValue != 0 )
266        {
267            fail( "Exit value wasn't 0, was:" + exitValue );
268        }
269    }
270
271    protected static void makeDirectory( File basedir, String fileName )
272    {
273        File dir = new File( basedir, fileName );
274
275        if ( !dir.exists() )
276        {
277            assertTrue( dir.mkdirs() );
278        }
279    }
280
281    protected static void makeFile( File basedir, String fileName )
282        throws IOException
283    {
284        makeFile( basedir, fileName, fileName );
285    }
286
287    public static void makeFile( File basedir, String fileName, String contents )
288        throws IOException
289    {
290        File file = new File( basedir, fileName );
291
292        File parent = file.getParentFile();
293
294        if ( !parent.exists() )
295        {
296            assertTrue( parent.mkdirs() );
297        }
298
299        try ( FileWriter writer = new FileWriter( file ) )
300        {
301            writer.write( contents );
302        }
303    }
304
305    protected void deleteDirectory( File directory )
306        throws IOException
307    {
308        FileUtils.deleteDirectory( directory );
309    }
310
311    public static Date getDate( int year, int month, int day )
312    {
313        return getDate( year, month, day, 0, 0, 0, null );
314    }
315
316    protected static Date getDate( int year, int month, int day, TimeZone tz )
317    {
318        return getDate( year, month, day, 0, 0, 0, tz );
319    }
320
321    protected static Date getDate( int year, int month, int day, int hourOfDay, int minute, int second, TimeZone tz )
322    {
323        Calendar cal = Calendar.getInstance();
324
325        if ( tz != null )
326        {
327            cal.setTimeZone( tz );
328        }
329        cal.set( year, month, day, hourOfDay, minute, second );
330        cal.set( Calendar.MILLISECOND, 0 );
331
332        return cal.getTime();
333    }
334
335    public void assertCommandLine( String expectedCommand, File expectedWorkingDirectory, Commandline actualCommand )
336        throws IOException
337    {
338        Commandline cl = new Commandline( expectedCommand );
339        if ( expectedWorkingDirectory != null )
340        {
341            cl.setWorkingDirectory( expectedWorkingDirectory.getAbsolutePath() );
342        }
343        String expectedCommandLineAsExecuted = StringUtils.join( cl.getShellCommandline(), " " );
344        String actualCommandLineAsExecuted = StringUtils.join( actualCommand.getShellCommandline(), " " );
345        assertEquals( expectedCommandLineAsExecuted, actualCommandLineAsExecuted );
346    }
347
348    public static void checkScmPresence( String scmProviderCommand )
349    {
350        assumeTrue( "Skipping tests because the required command '" + scmProviderCommand + "' is not available.",
351            ScmTestCase.isSystemCmd( scmProviderCommand ) );
352    }
353
354    /**
355     * @param cmd the executable to run, not null.
356     * @return true if and only if the command is on the path
357     */
358    public static boolean isSystemCmd( String cmd )
359    {
360        try
361        {
362            Runtime.getRuntime().exec( cmd );
363
364            return true;
365        }
366        catch ( IOException e )
367        {
368            return false;
369        }
370    }
371
372    public static void printSystemCmdUnavail( String cmd, String testName )
373    {
374        System.err.printf( "'%s' is not a system command. Ignored %s.%n", cmd, testName );
375    }
376}