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