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