001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.scm;
020
021import java.io.File;
022import java.io.FileWriter;
023import java.io.IOException;
024import java.util.Calendar;
025import java.util.Date;
026import java.util.TimeZone;
027
028import org.apache.maven.scm.manager.ScmManager;
029import org.apache.maven.scm.repository.ScmRepository;
030import org.codehaus.plexus.ContainerConfiguration;
031import org.codehaus.plexus.PlexusConstants;
032import org.codehaus.plexus.util.FileUtils;
033import org.codehaus.plexus.util.StringUtils;
034import org.codehaus.plexus.util.cli.CommandLineUtils;
035import org.codehaus.plexus.util.cli.CommandLineUtils.StringStreamConsumer;
036import org.codehaus.plexus.util.cli.Commandline;
037import org.junit.Before;
038
039import static org.junit.Assert.assertEquals;
040import static org.junit.Assert.assertFalse;
041import static org.junit.Assert.assertTrue;
042import static org.junit.Assert.fail;
043import static org.junit.Assume.assumeTrue;
044
045/**
046 * Base class for all SCM tests. Consumers will typically
047 * extend this class while tck test would extend ScmTckTestCase.
048 * <br>
049 * This class basically defines default locations for the
050 * test environment and implements convenience methods.
051 *
052 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
053 */
054public abstract class ScmTestCase extends PlexusJUnit4TestCase {
055    protected static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");
056
057    private static boolean debugExecute;
058
059    private ScmManager scmManager;
060
061    @Before
062    @Override
063    public void setUp() throws Exception {
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    @Override
081    public void customizeContainerConfiguration(final ContainerConfiguration configuration) {
082        configuration.setClassPathScanning(PlexusConstants.SCANNING_INDEX).setAutoWiring(true);
083    }
084
085    /**
086     * @return default location of the test read/write repository
087     */
088    protected File getRepositoryRoot() {
089        return PlexusJUnit4TestCase.getTestFile("target/scm-test/repository");
090    }
091
092    /**
093     * @return location of the revisioned (read only) repository
094     */
095    protected File getRepository() {
096        return PlexusJUnit4TestCase.getTestFile("/src/test/repository");
097    }
098
099    /**
100     * @return location of the working copy (always checkout)
101     */
102    protected File getWorkingCopy() {
103        return PlexusJUnit4TestCase.getTestFile("target/scm-test/working-copy");
104    }
105
106    /**
107     * Legacy method - same as getWorkingCopy()
108     *
109     * @return location of the working copy (always checkout)
110     */
111    protected File getWorkingDirectory() {
112        return getWorkingCopy();
113    }
114
115    /**
116     * @return default location for doing assertions on a working tree
117     */
118    protected File getAssertionCopy() {
119        return PlexusJUnit4TestCase.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        return PlexusJUnit4TestCase.getTestFile("target/scm-test/updating-copy");
127    }
128
129    protected ScmManager getScmManager() throws Exception {
130        if (scmManager == null) {
131            scmManager = lookup(ScmManager.class);
132        }
133
134        return scmManager;
135    }
136
137    protected ScmRepository makeScmRepository(String scmUrl) throws Exception {
138        return getScmManager().makeScmRepository(scmUrl);
139    }
140
141    public void assertPath(String expectedPath, String actualPath) throws Exception {
142        assertEquals(expectedPath.replace('\\', '/'), actualPath.replace('\\', '/'));
143    }
144
145    protected void assertFile(File root, String fileName) throws Exception {
146        File file = new File(root, fileName);
147
148        assertTrue("Missing file: '" + file.getAbsolutePath() + "'.", file.exists());
149
150        assertTrue("File isn't a file: '" + file.getAbsolutePath() + "'.", file.isFile());
151
152        String expected = fileName;
153
154        String actual = FileUtils.fileRead(file);
155
156        assertEquals(
157                "The file doesn't contain the expected contents. File: " + file.getAbsolutePath(), expected, actual);
158    }
159
160    protected void assertResultIsSuccess(ScmResult result) {
161        if (result.isSuccess()) {
162            return;
163        }
164
165        printOutputError(result);
166
167        fail("The command result success flag was false.");
168    }
169
170    protected void printOutputError(ScmResult result) {
171        System.err.println("----------------------------------------------------------------------");
172        System.err.println("Provider message");
173        System.err.println("----------------------------------------------------------------------");
174        System.err.println(result.getProviderMessage());
175        System.err.println("----------------------------------------------------------------------");
176
177        System.err.println("----------------------------------------------------------------------");
178        System.err.println("Command output");
179        System.err.println("----------------------------------------------------------------------");
180        System.err.println(result.getCommandOutput());
181        System.err.println("----------------------------------------------------------------------");
182    }
183
184    protected ScmFileSet getScmFileSet() {
185        return new ScmFileSet(getWorkingCopy());
186    }
187
188    protected static void setDebugExecute(boolean debugExecute) {
189        ScmTestCase.debugExecute = debugExecute;
190    }
191
192    /**
193     * Execute the command line.
194     *
195     * @param workingDirectory not null
196     * @param executable       not null, should be a system command
197     * @param arguments        not null
198     * @throws Exception if any
199     * @see CommandLineUtils#executeCommandLine(Commandline, org.codehaus.plexus.util.cli.StreamConsumer,
200     *      org.codehaus.plexus.util.cli.StreamConsumer)
201     */
202    public static void execute(File workingDirectory, String executable, String arguments) throws Exception {
203        Commandline cl = new Commandline();
204
205        cl.setExecutable(executable);
206
207        cl.setWorkingDirectory(workingDirectory.getAbsolutePath());
208
209        cl.addArguments(CommandLineUtils.translateCommandline(arguments));
210
211        StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
212
213        StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
214
215        System.out.println("Test command line: " + cl);
216
217        int exitValue = CommandLineUtils.executeCommandLine(cl, stdout, stderr);
218
219        if (debugExecute || exitValue != 0) {
220            System.err.println("-----------------------------------------");
221            System.err.println("Command line: " + cl);
222            System.err.println("Working directory: " + cl.getWorkingDirectory());
223            System.err.println("-----------------------------------------");
224            System.err.println("Standard output: ");
225            System.err.println("-----------------------------------------");
226            System.err.println(stdout.getOutput());
227            System.err.println("-----------------------------------------");
228
229            System.err.println("Standard error: ");
230            System.err.println("-----------------------------------------");
231            System.err.println(stderr.getOutput());
232            System.err.println("-----------------------------------------");
233        }
234
235        if (exitValue != 0) {
236            fail("Exit value wasn't 0, was:" + exitValue);
237        }
238    }
239
240    protected static void makeDirectory(File basedir, String fileName) {
241        File dir = new File(basedir, fileName);
242
243        if (!dir.exists()) {
244            assertTrue(dir.mkdirs());
245        }
246    }
247
248    protected static void makeFile(File basedir, String fileName) throws IOException {
249        makeFile(basedir, fileName, fileName);
250    }
251
252    public static void makeFile(File basedir, String fileName, String contents) throws IOException {
253        File file = new File(basedir, fileName);
254
255        File parent = file.getParentFile();
256
257        if (!parent.exists()) {
258            assertTrue(parent.mkdirs());
259        }
260
261        try (FileWriter writer = new FileWriter(file)) {
262            writer.write(contents);
263        }
264    }
265
266    protected void deleteDirectory(File directory) throws IOException {
267        FileUtils.deleteDirectory(directory);
268    }
269
270    public static Date getDate(int year, int month, int day) {
271        return getDate(year, month, day, 0, 0, 0, null);
272    }
273
274    protected static Date getDate(int year, int month, int day, TimeZone tz) {
275        return getDate(year, month, day, 0, 0, 0, tz);
276    }
277
278    protected static Date getDate(int year, int month, int day, int hourOfDay, int minute, int second, TimeZone tz) {
279        Calendar cal = Calendar.getInstance();
280
281        if (tz != null) {
282            cal.setTimeZone(tz);
283        }
284        cal.set(year, month, day, hourOfDay, minute, second);
285        cal.set(Calendar.MILLISECOND, 0);
286
287        return cal.getTime();
288    }
289
290    public void assertCommandLine(String expectedCommand, File expectedWorkingDirectory, Commandline actualCommand)
291            throws IOException {
292        Commandline cl = new Commandline(expectedCommand);
293        if (expectedWorkingDirectory != null) {
294            cl.setWorkingDirectory(expectedWorkingDirectory.getAbsolutePath());
295        }
296        String expectedCommandLineAsExecuted = StringUtils.join(cl.getShellCommandline(), " ");
297        String actualCommandLineAsExecuted = StringUtils.join(actualCommand.getShellCommandline(), " ");
298        assertEquals(expectedCommandLineAsExecuted, actualCommandLineAsExecuted);
299    }
300
301    public static void checkSystemCmdPresence(String scmProviderCommand) {
302        assumeTrue(
303                "Skipping tests because the required command '" + scmProviderCommand + "' is not available.",
304                ScmTestCase.isSystemCmd(scmProviderCommand));
305    }
306
307    /**
308     * @param cmd the executable to run, not null
309     * @return true if and only if the command is on the path
310     */
311    public static boolean isSystemCmd(String cmd) {
312        try {
313            Runtime.getRuntime().exec(cmd);
314
315            return true;
316        } catch (IOException e) {
317            return false;
318        }
319    }
320}