001    package 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    
022    import java.io.File;
023    import java.util.ArrayList;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.TreeMap;
028    
029    import org.apache.maven.scm.command.add.AddScmResult;
030    import org.apache.maven.scm.command.checkin.CheckInScmResult;
031    import org.apache.maven.scm.command.checkout.CheckOutScmResult;
032    import org.apache.maven.scm.provider.ScmProvider;
033    import org.apache.maven.scm.repository.ScmRepository;
034    import org.codehaus.plexus.util.StringUtils;
035    
036    /**
037     * <p/>
038     * Base class for all TcK tests.
039     * </p>
040     * <p/>
041     * Basically all it does is to setup a default test enviroment
042     * common for all tck tests. The default setup includes:
043     * <ol>
044     * <li>Delete all default locations (working copy, updating copy etc)</li>
045     * <li>Initialize the repository</li>
046     * <li>Check out the repository to the working copy</li>
047     * </ol>
048     * </p>
049     *
050     * @author <a href="mailto:torbjorn@smorgrav.org">Torbj�rn Eikli Sm�rgrav</a>
051     *
052     */
053    public abstract class ScmTckTestCase
054        extends ScmTestCase
055    {
056        private ScmRepository scmRepository;
057    
058        private List<String> scmFileNames;
059    
060        /**
061         * @return A provider specific and valid url for the repository
062         * @throws Exception if any
063         */
064        public abstract String getScmUrl()
065            throws Exception;
066    
067        /**
068         * <p/>
069         * Get the list of file names that is supposed to be in the test repo.
070         * </p>
071         * <ul>
072         * <li>/pom.xml</li>
073         * <li>/readme.txt</li>
074         * <li>/src/main/java/Application.java</li>
075         * <li>/src/test/java/Test.java</li>
076         * </ul>
077         *
078         * @return {@link List} of {@link String} objects
079         */
080        protected List<String> getScmFileNames()
081        {
082            return scmFileNames;
083        }
084    
085        /**
086         * <p/>
087         * Initialize repository at the {@link #getScmUrl()} location with the files in {@link #getScmFileNames()}
088         * </p>
089         * <p/>
090         * The setup is also asserting on the existence of these files. <br>
091         * This should only be used by this class (thus do not call this method from derived classes)
092         * </p>
093         * <b>Note</b>: 'svnadmin' should be a system command.
094         *
095         * @throws Exception if any
096         */
097        public abstract void initRepo()
098            throws Exception;
099    
100        /**
101         * {@inheritDoc}
102         */
103        protected void setUp()
104            throws Exception
105        {
106            super.setUp();
107    
108            scmRepository = null;
109    
110            scmFileNames = new ArrayList<String>( 4 );
111            scmFileNames.add( "/pom.xml" );
112            scmFileNames.add( "/readme.txt" );
113            scmFileNames.add( "/src/main/java/Application.java" );
114            scmFileNames.add( "/src/test/java/Test.java" );
115    
116            initRepo();
117    
118            checkOut( getWorkingCopy(), getScmRepository() );
119    
120            Iterator<String> it = getScmFileNames().iterator();
121            while ( it.hasNext() )
122            {
123                assertFile( getWorkingCopy(), it.next() );
124            }
125        }
126    
127        /**
128         * This method is available to those SCM clients that need to perform
129         * a cleanup at the end of the tests. It is needed when server side
130         * operations are performed, or the check out dirs are outside
131         * of the normal target directory.
132         */
133        public void removeRepo()
134            throws Exception
135        {
136        }
137    
138        /**
139         * Provided to allow removeRepo() to be called. 
140         * @see junit.framework.TestCase#tearDown()
141         */
142        @Override
143        protected void tearDown()
144            throws Exception
145        {
146            super.tearDown();
147            removeRepo();
148        }
149    
150        /**
151         * Convenience method to get the ScmRepository for this provider
152         */
153        protected ScmRepository getScmRepository()
154            throws Exception
155        {
156            if ( scmRepository == null )
157            {
158                scmRepository = getScmManager().makeScmRepository( getScmUrl() );
159            }
160    
161            return scmRepository;
162        }
163    
164        /**
165         * Convenience method to check out files from the repository
166         */
167        protected CheckOutScmResult checkOut( File workingDirectory, ScmRepository repository )
168            throws Exception
169        {
170            CheckOutScmResult result =
171                getScmManager().getProviderByUrl( getScmUrl() ).checkOut( repository, new ScmFileSet( workingDirectory ),
172                                                                          (ScmVersion) null );
173    
174            assertTrue( "Check result was successful, output: " + result.getCommandOutput(), result.isSuccess() );
175    
176            return result;
177        }
178    
179        /**
180         * Convenience method to check in files to the repository
181         */
182        protected CheckInScmResult checkIn( File workingDirectory, ScmRepository repository )
183            throws Exception
184        {
185            CheckInScmResult result = getScmManager().getProviderByUrl( getScmUrl() )
186                .checkIn( repository, new ScmFileSet( workingDirectory ), (ScmVersion) null, "Initial Checkin" );
187    
188            assertTrue( "Check result was successful, output: " + result.getCommandOutput(), result.isSuccess() );
189    
190            return result;
191        }
192        
193        /**
194         * Convenience method to add a file to the working tree at the working directory
195         */
196        protected void addToWorkingTree( File workingDirectory, File file, ScmRepository repository )
197            throws Exception
198        {
199            ScmProvider provider = getScmManager().getProviderByUrl( getScmUrl() );
200    
201            CommandParameters commandParameters = new CommandParameters();
202            commandParameters.setString( CommandParameter.FORCE_ADD, Boolean.TRUE.toString() );
203    
204            AddScmResult result = provider.add( repository, new ScmFileSet( workingDirectory, file ), commandParameters );
205    
206            assertTrue( "Check result was successful, output: " + result.getCommandOutput(), result.isSuccess() );
207    
208            List<ScmFile> addedFiles = result.getAddedFiles();
209    
210            if ( new File( workingDirectory, file.getPath() ).isFile() )
211            {
212                // Don't check directory add because some SCM tools ignore it
213                assertEquals( "Expected 1 file in the added files list " + addedFiles, 1, addedFiles.size() );
214            }
215        }
216    
217        /**
218         * take the files of the given list, add them to a TreeMap and
219         * use the pathName String as key for the Map.
220         * This function is useful for every TCK which has to check for the
221         * existence of more than 1 file of the returned ScmResult, regardless
222         * of their order in the list.
223         * All backslashes in the path will be replaced by forward slashes
224         * for Windows compatibility.
225         *
226         * @param files List with {@code ScmFile}s
227         * @return Map key=pathName, value=ScmFile
228         */
229        protected Map<String, ScmFile> mapFilesByPath( List<ScmFile> files )
230        {
231            if ( files == null )
232            {
233                return null;
234            }
235    
236            Map<String, ScmFile> mappedFiles = new TreeMap<String, ScmFile>();
237            for ( ScmFile scmFile : files )
238            {
239                String path = StringUtils.replace( scmFile.getPath(), "\\", "/" );
240                mappedFiles.put( path, scmFile );
241            }
242    
243            return mappedFiles;
244        }
245    }