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