/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001-2003, 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.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import junit.framework.TestCase;
import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.Modification;
import net.sourceforge.cruisecontrol.util.Commandline;
import net.sourceforge.cruisecontrol.util.StreamPumper;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
/**
* @author Robert Watkins
* @author Jason Yip, jcyip@thoughtworks.com
* @author Patrick Conant Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
* Licensed under the CruiseControl BSD license
*/
public class P4Test extends TestCase {
/**
* Mocks a P4 class by returning a specific P4 server-time offset
*/
static class MockP4 extends P4 {
private final long timeOffset;
public MockP4(long offset) {
this.timeOffset = offset;
}
protected long calculateServerTimeOffset() {
return timeOffset;
}
}
public void testGetQuoteChar() {
boolean windows = true;
String quoteChar = P4.getQuoteChar(windows);
assertEquals("\"", quoteChar);
quoteChar = P4.getQuoteChar(!windows);
assertEquals("'", quoteChar);
}
public void testValidate() {
P4 p4 = new P4();
try {
p4.validate();
fail("P4 should throw exceptions when required attributes are not set.");
} catch (CruiseControlException expected) {
}
p4.setUser("user");
p4.setPort("port");
p4.setClient("client");
p4.setView("view");
try {
p4.validate();
} catch (CruiseControlException e) {
fail("P4 should not throw exceptions when required attributes are set.");
}
}
public void testBuildChangesCommand() throws Exception {
P4 p4 = new MockP4(0);
p4.setView("foo");
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
Date date = dateFormat.parse("12/30/2004");
Commandline cmdLine = p4.buildChangesCommand(date, date);
String[] args = cmdLine.getCommandline();
StringBuffer cmd = new StringBuffer();
cmd.append(args[0]);
for (int i = 1; i < args.length; i++) {
cmd.append(" ").append(args[i]);
}
assertEquals("p4 -s changes -s submitted foo@2004/12/30:00:00:00,@2004/12/30:00:00:00", cmd.toString());
}
public void testBuildChangesCommand_Unix() throws Exception {
P4 p4 = new MockP4(0);
p4.setView("foo");
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
Date date = dateFormat.parse("12/30/2004");
Commandline cmdLine = p4.buildChangesCommand(date, date);
String[] args = cmdLine.getCommandline();
StringBuffer cmd = new StringBuffer();
cmd.append(args[0]);
for (int i = 1; i < args.length; i++) {
cmd.append(" ").append(args[i]);
}
assertEquals("p4 -s changes -s submitted foo@2004/12/30:00:00:00,@2004/12/30:00:00:00", cmd.toString());
}
public void testBuildInfoCommand() {
P4 p4 = new P4();
Commandline command = p4.buildInfoCommand();
assertEquals("p4 info", command.toString());
p4.setPort("1234");
command = p4.buildInfoCommand();
assertEquals("p4 -p 1234 info", command.toString());
}
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 testParseChangelists() throws IOException {
BufferedInputStream input = new BufferedInputStream(loadTestLog("p4_changes.txt"));
P4 p4 = new P4();
String[] changelists = p4.parseChangelistNumbers(input);
input.close();
assertNotNull("No changelists returned", changelists);
assertEquals("Returned wrong number of changelists", 4, changelists.length);
String[] expectedChangelists = new String[] { "14", "12", "11" };
for (int i = 0; i < expectedChangelists.length; i++) {
assertEquals("Returned wrong changelist number", expectedChangelists[i], changelists[i]);
}
}
public void testParseChangeDescriptions() throws Exception {
BufferedInputStream input = new BufferedInputStream(loadTestLog("p4_describe.txt"));
P4 p4 = new P4();
p4.setCorrectForServerTime(false);
List changelists = p4.parseChangeDescriptions(input);
input.close();
assertEquals("Returned wrong number of changelists", 3, changelists.size());
assertEquals("Wrong description", "Fixed support for db2. This is now the default database shipped"
+ " with HPDoc. For now that is. Still has to be tested on"
+ " PostgreSQL to see that it is still working there. The sea rch"
+ " mechanism is also upgraded to now ALMOST support AND/OR"
+ " expressions. There are thoughtsabout this, but not yet implemented (however prepared for)",
((Modification) changelists.get(0)).comment);
checkModifications((Modification) changelists.get(0), "//depot/hpdoc/main", 33);
assertEquals("Wrong description", "ok, tests running smooth. Checking in mostly for backup. Not"
+ " finished yet. CIMD is comming on great and I'm starting to see a framework developing.",
((Modification) changelists.get(1)).comment);
checkModifications((Modification) changelists.get(1), "//depot/k4j/main", 65);
assertEquals("Wrong description", "Testing ..\nSome ..\nLinebreaks.",
((Modification) changelists.get(2)).comment);
checkModifications((Modification) changelists.get(2), "", 0);
}
/**
* Check that all modifications match expected values.
*
* @param modification
* The modification to be checked
* @param depotPrefix
* The prefix all filenames are expected to start with.
* @param modCount
* The expected number of files changes in this modification.
* @throws MalformedPatternException if something fails
*/
public void checkModifications(final Modification modification, final String depotPrefix, final int modCount)
throws MalformedPatternException {
final List<Modification.ModifiedFile> changeList = modification.files;
assertEquals("Wrong number of entries", modCount, changeList.size());
for (final Modification.ModifiedFile file : changeList) {
assertTrue("Filename doesn't start with prefix " + depotPrefix, file.fileName.startsWith(depotPrefix));
assertEquals("Filename has # at bad index", -1, file.fileName.indexOf("#"));
assertTrue("Revision doesn't match regexp ^\\d+$: " + file.revision, matches(file.revision, "^\\d+$"));
assertTrue("Unknown action type: " + file.action, matches(file.action, "(edit|add)"));
}
}
public void testParseInfoResponse() throws IOException {
BufferedInputStream input = new BufferedInputStream(loadTestLog("p4_info.txt"));
Calendar cal = Calendar.getInstance();
// this date is encoded in p4_info.txt. Note month is indexed from 0
cal.set(2005, 6, 29, 20, 39, 6);
long p4ServerTime = cal.getTime().getTime();
long ccServerTime = System.currentTimeMillis();
long expectedOffset = p4ServerTime - ccServerTime;
P4.ServerInfoConsumer serverInfo = new P4.ServerInfoConsumer();
new StreamPumper(input, serverInfo).run();
long offset = serverInfo.getOffset();
// Need to accept some difference in the expected offset and the actual
// offset, because the test takes some time to run. To be safe, we'll
// allow up to 1 minute of variability in the offset value.
long maxOffset = 1000 * 60;
long offsetDifference = Math.abs(offset - expectedOffset);
assertTrue("Server time offset wasn't calculated accurately. Expected " + expectedOffset + " but got "
+ offset + ". Maximum allowed" + "difference in these values is " + maxOffset
+ ". P4 server time (from test input) is " + p4ServerTime + "; CC server time is " + ccServerTime,
offsetDifference < maxOffset);
}
public boolean matches(String str, String pattern) throws MalformedPatternException {
return new Perl5Matcher().matches(str, new Perl5Compiler().compile(pattern));
}
// public void testGetModifications() throws Exception {
//
// // REAL TEST IF YOU NEED IT
// P4 p4 = new P4();
// p4.setView("//depot/...");
// List changelists = p4.getModifications(new Date(0), new Date(), 0);
// assertEquals("Returned wrong number of changelists", 3,
// changelists.size());
//
// }
public static void main(String[] args) {
junit.textui.TestRunner.run(P4Test.class);
}
}