/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2007, ThoughtWorks, Inc. * 200 E. Randolph, 25th Floor * Chicago, IL 60601 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package net.sourceforge.cruisecontrol.sourcecontrols; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TimeZone; import junit.framework.TestCase; import net.sourceforge.cruisecontrol.CruiseControlException; import net.sourceforge.cruisecontrol.Modification; import net.sourceforge.cruisecontrol.testutil.TestUtil; import org.jdom.JDOMException; /** * @author <a href="jerome@coffeebreaks.org">Jerome Lacoste</a> * @see <a href="http://www.selenic.com/mercurial">Mercurial web site</a> */ public class MercurialTest extends TestCase { private Mercurial mercurial; private TimeZone originalTimeZone; private File tempFile; protected void setUp() throws Exception { mercurial = new Mercurial(); mercurial.setLocalWorkingCopy("."); originalTimeZone = TimeZone.getDefault(); tempFile = File.createTempFile("temp", "txt"); tempFile.deleteOnExit(); } protected void tearDown() throws Exception { TimeZone.setDefault(originalTimeZone); } public void testValidateNoAttributesSet() throws IOException { try { new Mercurial().validate(); } catch (CruiseControlException e) { fail("should not throw an exception when no attributes are set " + e.getMessage()); } } public void testValidatInvalidLocalWorkingCopy() throws IOException { mercurial.setLocalWorkingCopy("invalid directory"); try { mercurial.validate(); fail("should throw an exception when an invalid 'localWorkingCopy' attribute is set"); } catch (CruiseControlException e) { // expected } } public void testValidateValidLocalWorkingCopy() throws IOException { mercurial.setLocalWorkingCopy(tempFile.getParent()); try { mercurial.validate(); } catch (CruiseControlException e) { fail( "should not throw an exception when at least a valid 'localWorkingCopy' " + "attribute is set"); } } public void testValidateFailWhenLocalWorkingCopyIsAFile() throws IOException { mercurial.setLocalWorkingCopy(tempFile.getAbsolutePath()); try { mercurial.validate(); fail("should throw an exception when 'localWorkingCopy' is file instead of directory."); } catch (CruiseControlException e) { // expected } } public void testValidatePassIfHgCommandIsIncomingOrLog() throws Exception { try { mercurial.setHgCommand("incoming"); mercurial.validate(); mercurial.setHgCommand("log"); mercurial.validate(); } catch (CruiseControlException e) { fail("should not throw an exception when hgcommand is either incoming or log"); } } public void testValidateFailIfHgCommandIsNeitherIncomingNorLog() throws Exception { try { mercurial.setHgCommand("in"); mercurial.validate(); fail("should throw an exception when hgcommand is neither incoming nor log"); } catch (CruiseControlException e) { // expected, even the command is in, which's the alias of incoming } } public void testShouldUseLogToGetModificationsIfHgCommandIsLog() throws Exception { Date from = Mercurial.HG_DATE_PARSER.parse("1978-03-06 17:33:55 +0000"); Date to = Mercurial.HG_DATE_PARSER.parse("2978-03-06 17:33:55 +0000"); String[] expectedCmd = new String[] { "hg", "log", "--debug", "--date", Mercurial.HG_DATE_PARSER.format(from) + " to " + Mercurial.HG_DATE_PARSER.format(to), "--template", Mercurial.MODIFICATION_XML_TEMPLATE, new File(".").getAbsolutePath() }; mercurial.setHgCommand("log"); String[] actualCmd = mercurial.buildHistoryCommand(from, to).getCommandline(); TestUtil.assertArray("", expectedCmd, actualCmd); } public void testShouldUseIncomingToGetModificationsByDefaultSoThatItWontBreakExistingConfig() throws Exception { Date from = Mercurial.HG_DATE_PARSER.parse("1978-03-06 17:33:55 +0000"); Date to = Mercurial.HG_DATE_PARSER.parse("2978-03-06 17:33:55 +0000"); String[] expectedCmd = new String[] { "hg", "incoming", "--debug", "--template", Mercurial.MODIFICATION_XML_TEMPLATE }; String[] actualCmd = mercurial.buildHistoryCommand(from, to).getCommandline(); TestUtil.assertArray("", expectedCmd, actualCmd); } public void testParseModifications() throws JDOMException, ParseException, IOException { BufferedInputStream input = new BufferedInputStream(loadTestLog("mercurial_incoming_xml_debug.txt")); List modifications = Mercurial.parseStream(input); input.close(); assertEquals("Should have returned 7 modifications.", 7, modifications.size()); Modification modification = createModification( parseIso8601Format("2007-08-27 16:11:19 +0200"), "ET4642@localhost", "Test of a fourth commit", "3:bb0a5f00315f4f6dddb7362a69bc0910b07c4faa", "", "file1.txt", "modified"); assertEquals(modification, modifications.get(0)); modification = createModification( parseIso8601Format("2007-08-29 21:38:18 +0200"), "ET4642@edbwp000856.edb.local", "Changed 2 files", "4:1da89ee88532fddb21235b2d21e4a46424adbe39", "", "file1.txt", "modified"); assertEquals(modification, modifications.get(1)); modification = createModification( parseIso8601Format("2007-08-29 21:38:18 +0200"), "ET4642@edbwp000856.edb.local", "Changed 2 files", "4:1da89ee88532fddb21235b2d21e4a46424adbe39", "", "file2.txt", "modified"); assertEquals(modification, modifications.get(2)); modification = createModification( parseIso8601Format("2007-08-29 21:44:37 +0200"), "ET4642@edbwp000856.edb.local", "new change, with one directory depth", "5:93981bd125719a98d7c11028560b2b736b3f12ec", "", "file2.txt", "modified"); assertEquals(modification, modifications.get(3)); modification = createModification( parseIso8601Format("2007-08-29 21:44:37 +0200"), "ET4642@edbwp000856.edb.local", "new change, with one directory depth", "5:93981bd125719a98d7c11028560b2b736b3f12ec", "", "mydir/newfile.txt", "added"); assertEquals(modification, modifications.get(4)); modification = createModification( parseIso8601Format("2007-08-30 09:09:08 +0200"), "ET4642@localhost", "removed one file, changed one", "6:e3cefb520ddc6c7de8bad83f17df4b3d4194fe08", "", "file2.txt", "removed"); assertEquals(modification, modifications.get(5)); modification = createModification( parseIso8601Format("2007-08-30 09:09:08 +0200"), "ET4642@localhost", "removed one file, changed one", "6:e3cefb520ddc6c7de8bad83f17df4b3d4194fe08", "", "file1.txt", "modified"); assertEquals(modification, modifications.get(6)); } private Date parseIso8601Format(String iso8601Date) throws ParseException { return Mercurial.HG_DATE_PARSER.parse(iso8601Date); } private InputStream loadTestLog(String name) { InputStream testStream = getClass().getResourceAsStream(name); assertNotNull("failed to load resource " + name + " in class " + getClass().getName(), testStream); return testStream; } public void testSetPropertyNoChanges() throws ParseException { mercurial.setProperty("hasChanges?"); List noModifications = new ArrayList(); mercurial.fillPropertiesIfNeeded(noModifications); assertFalse(mercurial.getProperties().containsKey("hasChanges?")); assertEquals(null, mercurial.getProperties().get("hgrevision")); } public void testSetPropertyHasChanges() throws ParseException { mercurial.setProperty("hasChanges?"); final List<Modification> hasModifications = new ArrayList<Modification>(); hasModifications.add(createModification( parseIso8601Format("2007-08-27 16:11:19 +0200"), "ET4642@localhost", "Test of a fourth commit", "3:bb0a5f00315f4f6dddb7362a69bc0910b07c4faa", "", "file1.txt", "modified")); hasModifications.add(createModification( parseIso8601Format("2007-08-29 21:38:18 +0200"), "ET4642@edbwp000856.edb.local", "Changed 2 files", "4:1da89ee88532fddb21235b2d21e4a46424adbe39", "", "file1.txt", "modified")); mercurial.fillPropertiesIfNeeded(hasModifications); final Map<String, String> properties = mercurial.getProperties(); assertEquals("true", properties.get("hasChanges?")); assertEquals("4:1da89ee88532fddb21235b2d21e4a46424adbe39", properties.get("hgrevision")); } public void testSetPropertyIgnoresPriorState() throws ParseException { testSetPropertyHasChanges(); mercurial.fillPropertiesIfNeeded(new ArrayList()); assertFalse(mercurial.getProperties().containsKey("hasChanges?")); } public void testSetPropertyOnDeleteEmptyModifications() throws ParseException { mercurial.setPropertyOnDelete("hasDeletions?"); List noModifications = new ArrayList(); mercurial.fillPropertiesIfNeeded(noModifications); assertEquals(null, mercurial.getProperties().get("hasDeletions?")); } public void testSetPropertyOnDeleteNoDeletion() throws ParseException { mercurial.setPropertyOnDelete("hasDeletions?"); final List<Modification> noDeletions = new ArrayList<Modification>(); noDeletions.add(createModification( parseIso8601Format("2007-08-27 16:11:19 +0200"), "ET4642@localhost", "Test of a fourth commit", "3:bb0a5f00315f4f6dddb7362a69bc0910b07c4faa", "", "file1.txt", "modified")); mercurial.fillPropertiesIfNeeded(noDeletions); assertEquals(null, mercurial.getProperties().get("hasDeletions?")); } public void testSetPropertyOnDeleteHasDeletion() throws ParseException { mercurial.setPropertyOnDelete("hasDeletions?"); final List<Modification> hasDeletions = new ArrayList<Modification>(); hasDeletions.add(createModification( parseIso8601Format("2007-08-27 16:11:19 +0200"), "ET4642@localhost", "Test of a fourth commit", "3:bb0a5f00315f4f6dddb7362a69bc0910b07c4faa", "", "file1.txt", "modified")); hasDeletions.add(createModification( parseIso8601Format("2007-08-29 21:38:18 +0200"), "ET4642@edbwp000856.edb.local", "Changed 2 files", "4:1da89ee88532fddb21235b2d21e4a46424adbe39", "", "file1.txt", "deleted")); mercurial.fillPropertiesIfNeeded(hasDeletions); assertEquals("true", mercurial.getProperties().get("hasDeletions?")); } private static Modification createModification( Date date, String user, String comment, String revision, String folder, String file, String type) { Modification modification = new Modification("mercurial"); Modification.ModifiedFile modifiedFile = modification.createModifiedFile(file, folder); modifiedFile.action = type; modifiedFile.revision = revision; modification.modifiedTime = date; modification.userName = user; modification.comment = comment; modification.revision = revision; return modification; } public void testParseVersion() throws JDOMException, IOException, ParseException { BufferedInputStream input = new BufferedInputStream(loadTestLog("mercurial_version.txt")); String version = Mercurial.parseVersionStream(input); input.close(); assertEquals("version 0.9.4", version); } public void testBuildVersionCommand() throws CruiseControlException { mercurial.setLocalWorkingCopy("."); String[] expectedCmd = { "hg", "version" }; String[] actualCmd = mercurial.buildVersionCommand().getCommandline(); TestUtil.assertArray("", expectedCmd, actualCmd); } }