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 *
054 */
055public abstract class ScmTestCase extends PlexusJUnit4TestCase {
056    protected static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");
057
058    private static boolean debugExecute;
059
060    private ScmManager scmManager;
061
062    @Before
063    @Override
064    public void setUp() throws Exception {
065        super.setUp();
066
067        deleteDirectory(getRepositoryRoot());
068        assertFalse(getRepositoryRoot().exists());
069        deleteDirectory(getWorkingCopy());
070        assertFalse(getWorkingCopy().exists());
071        deleteDirectory(getWorkingDirectory());
072        assertFalse(getWorkingDirectory().exists());
073        deleteDirectory(getAssertionCopy());
074        assertFalse(getAssertionCopy().exists());
075        deleteDirectory(getUpdatingCopy());
076        assertFalse(getUpdatingCopy().exists());
077
078        scmManager = null;
079    }
080
081    @Override
082    public void customizeContainerConfiguration(final ContainerConfiguration configuration) {
083        configuration.setClassPathScanning(PlexusConstants.SCANNING_INDEX).setAutoWiring(true);
084    }
085
086    /**
087     * @return default location of the test read/write repository
088     */
089    protected File getRepositoryRoot() {
090        return PlexusJUnit4TestCase.getTestFile("target/scm-test/repository");
091    }
092
093    /**
094     * @return Location of the revisioned (read only) repository
095     */
096    protected File getRepository() {
097        return PlexusJUnit4TestCase.getTestFile("/src/test/repository");
098    }
099
100    /**
101     * @return location of the working copy (always checkout)
102     */
103    protected File getWorkingCopy() {
104        return PlexusJUnit4TestCase.getTestFile("target/scm-test/working-copy");
105    }
106
107    /**
108     * Legacy method - same as getWorkingCopy()
109     *
110     * @return location of the working copy (always checkout)
111     */
112    protected File getWorkingDirectory() {
113        return getWorkingCopy();
114    }
115
116    /**
117     * @return default location for doing assertions on a working tree
118     */
119    protected File getAssertionCopy() {
120        return PlexusJUnit4TestCase.getTestFile("target/scm-test/assertion-copy");
121    }
122
123    /**
124     * @return default location for doing update operations on a working tree
125     */
126    protected File getUpdatingCopy() {
127        return PlexusJUnit4TestCase.getTestFile("target/scm-test/updating-copy");
128    }
129
130    protected ScmManager getScmManager() throws Exception {
131        if (scmManager == null) {
132            scmManager = lookup(ScmManager.class);
133        }
134
135        return scmManager;
136    }
137
138    protected ScmRepository makeScmRepository(String scmUrl) throws Exception {
139        return getScmManager().makeScmRepository(scmUrl);
140    }
141
142    public void assertPath(String expectedPath, String actualPath) throws Exception {
143        assertEquals(expectedPath.replace('\\', '/'), actualPath.replace('\\', '/'));
144    }
145
146    protected void assertFile(File root, String fileName) throws Exception {
147        File file = new File(root, fileName);
148
149        assertTrue("Missing file: '" + file.getAbsolutePath() + "'.", file.exists());
150
151        assertTrue("File isn't a file: '" + file.getAbsolutePath() + "'.", file.isFile());
152
153        String expected = fileName;
154
155        String actual = FileUtils.fileRead(file);
156
157        assertEquals(
158                "The file doesn't contain the expected contents. File: " + file.getAbsolutePath(), expected, actual);
159    }
160
161    protected void assertResultIsSuccess(ScmResult result) {
162        if (result.isSuccess()) {
163            return;
164        }
165
166        printOutputError(result);
167
168        fail("The command result success flag was false.");
169    }
170
171    protected void printOutputError(ScmResult result) {
172        System.err.println("----------------------------------------------------------------------");
173        System.err.println("Provider message");
174        System.err.println("----------------------------------------------------------------------");
175        System.err.println(result.getProviderMessage());
176        System.err.println("----------------------------------------------------------------------");
177
178        System.err.println("----------------------------------------------------------------------");
179        System.err.println("Command output");
180        System.err.println("----------------------------------------------------------------------");
181        System.err.println(result.getCommandOutput());
182        System.err.println("----------------------------------------------------------------------");
183    }
184
185    protected ScmFileSet getScmFileSet() {
186        return new ScmFileSet(getWorkingCopy());
187    }
188
189    protected static void setDebugExecute(boolean debugExecute) {
190        ScmTestCase.debugExecute = debugExecute;
191    }
192
193    /**
194     * Execute the command line
195     *
196     * @param workingDirectory not null
197     * @param executable       not null, should be a system command
198     * @param arguments        not null
199     * @throws Exception if any
200     * @see CommandLineUtils#executeCommandLine(Commandline, org.codehaus.plexus.util.cli.StreamConsumer,
201     *      org.codehaus.plexus.util.cli.StreamConsumer)
202     */
203    public static void execute(File workingDirectory, String executable, String arguments) throws Exception {
204        Commandline cl = new Commandline();
205
206        cl.setExecutable(executable);
207
208        cl.setWorkingDirectory(workingDirectory.getAbsolutePath());
209
210        cl.addArguments(CommandLineUtils.translateCommandline(arguments));
211
212        StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
213
214        StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
215
216        System.out.println("Test command line: " + cl);
217
218        int exitValue = CommandLineUtils.executeCommandLine(cl, stdout, stderr);
219
220        if (debugExecute || exitValue != 0) {
221            System.err.println("-----------------------------------------");
222            System.err.println("Command line: " + cl);
223            System.err.println("Working directory: " + cl.getWorkingDirectory());
224            System.err.println("-----------------------------------------");
225            System.err.println("Standard output: ");
226            System.err.println("-----------------------------------------");
227            System.err.println(stdout.getOutput());
228            System.err.println("-----------------------------------------");
229
230            System.err.println("Standard error: ");
231            System.err.println("-----------------------------------------");
232            System.err.println(stderr.getOutput());
233            System.err.println("-----------------------------------------");
234        }
235
236        if (exitValue != 0) {
237            fail("Exit value wasn't 0, was:" + exitValue);
238        }
239    }
240
241    protected static void makeDirectory(File basedir, String fileName) {
242        File dir = new File(basedir, fileName);
243
244        if (!dir.exists()) {
245            assertTrue(dir.mkdirs());
246        }
247    }
248
249    protected static void makeFile(File basedir, String fileName) throws IOException {
250        makeFile(basedir, fileName, fileName);
251    }
252
253    public static void makeFile(File basedir, String fileName, String contents) throws IOException {
254        File file = new File(basedir, fileName);
255
256        File parent = file.getParentFile();
257
258        if (!parent.exists()) {
259            assertTrue(parent.mkdirs());
260        }
261
262        try (FileWriter writer = new FileWriter(file)) {
263            writer.write(contents);
264        }
265    }
266
267    protected void deleteDirectory(File directory) throws IOException {
268        FileUtils.deleteDirectory(directory);
269    }
270
271    public static Date getDate(int year, int month, int day) {
272        return getDate(year, month, day, 0, 0, 0, null);
273    }
274
275    protected static Date getDate(int year, int month, int day, TimeZone tz) {
276        return getDate(year, month, day, 0, 0, 0, tz);
277    }
278
279    protected static Date getDate(int year, int month, int day, int hourOfDay, int minute, int second, TimeZone tz) {
280        Calendar cal = Calendar.getInstance();
281
282        if (tz != null) {
283            cal.setTimeZone(tz);
284        }
285        cal.set(year, month, day, hourOfDay, minute, second);
286        cal.set(Calendar.MILLISECOND, 0);
287
288        return cal.getTime();
289    }
290
291    public void assertCommandLine(String expectedCommand, File expectedWorkingDirectory, Commandline actualCommand)
292            throws IOException {
293        Commandline cl = new Commandline(expectedCommand);
294        if (expectedWorkingDirectory != null) {
295            cl.setWorkingDirectory(expectedWorkingDirectory.getAbsolutePath());
296        }
297        String expectedCommandLineAsExecuted = StringUtils.join(cl.getShellCommandline(), " ");
298        String actualCommandLineAsExecuted = StringUtils.join(actualCommand.getShellCommandline(), " ");
299        assertEquals(expectedCommandLineAsExecuted, actualCommandLineAsExecuted);
300    }
301
302    public static void checkScmPresence(String scmProviderCommand) {
303        assumeTrue(
304                "Skipping tests because the required command '" + scmProviderCommand + "' is not available.",
305                ScmTestCase.isSystemCmd(scmProviderCommand));
306    }
307
308    /**
309     * @param cmd the executable to run, not null.
310     * @return true if and only if the command is on the path
311     */
312    public static boolean isSystemCmd(String cmd) {
313        try {
314            Runtime.getRuntime().exec(cmd);
315
316            return true;
317        } catch (IOException e) {
318            return false;
319        }
320    }
321}