/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2001, 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.testutil; import junit.framework.Assert; import net.sourceforge.cruisecontrol.util.IO; import org.jdom.Document; import org.jdom.Element; import java.io.IOException; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Map.Entry; import java.util.Set; import java.util.Vector; public final class TestUtil { public static class FilesToDelete { private final List<File> files = new Vector<File>(); public File add(File file) { files.add(file); return file; } public File add(String file) throws IOException { return add(file, null); } /** * Creates an empty file in the default temporary-file directory, using the name * of the object's class as the prefix. Automatically adds the name into the list of files * hold by the class. * @param obj the calling class (used to get its name as temporary file pattern) * @return a new temp file * @throws IOException when the file cannot be created */ public File add(Object obj) throws IOException { return add(obj.getClass().getName(), null); } /** * Creates an empty file in the default temporary-file directory, using the given prefix * and suffix to generate its name. Automatically adds the name into the list of files * hold by the class. * @param prefix the prefix string passed to {@link File.createTempFile(String, String)} * @param suffix the suffix string passed to {@link File.createTempFile(String, String)} * @return a new file * @throws IOException when the file cannot be created */ public File add(String prefix, String suffix) throws IOException { final File file = File.createTempFile(prefix, suffix); return add(file); } public void delete() { for (File file : files) { IO.delete(file); } files.clear(); } } /** * Records and restores properties get by System.get ... */ public static class PropertiesRestorer { private Properties recordedProps; /** * Stores all properties as they are defined in the time of the call of the method. * It is recommended to call this method in @link {@link TestCase#setUp()} or in the constructor * of a particular test */ public void record() { // TODO: if shallow copy of keys and values is not enough, make deep copy recordedProps = (Properties) System.getProperties().clone(); } /** * Resets properties into the state as they were recorded in @link {@link #record()}. * It is recommended to call this method in @link {@link TestCase#tearDown()}. */ public void restore() { System.setProperties(recordedProps); } } private static File targetDir; public static File getTargetDir() { if (targetDir == null) { final URL url; url = TestUtil.class.getClassLoader().getResource("net/sourceforge/cruisecontrol/BuilderTest.class"); final File classFile; try { classFile = new File(URLDecoder.decode(url.getPath(), "utf-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } targetDir = classFile.getParentFile().getParentFile().getParentFile().getParentFile().getParentFile(); final String absPath = targetDir.getAbsolutePath(); Assert.assertTrue("Unit test 'target' dir not a dir: " + absPath, targetDir.isDirectory()); Assert.assertTrue("Unit test 'target' does not exist: " + absPath, targetDir.exists()); Assert.assertEquals("Unit test 'target' dir has unexpected name: " + absPath, "target", targetDir.getName()); } return targetDir; } private TestUtil() { } public static Element createPassingBuild() { return createElement(true, true); } public static Element createFixedBuild() { return createElement(true, false); } public static Element createFailedBuild() { return createElement(false, false); } public static Element createElement(boolean success, boolean lastBuildSuccess) { return createElement(success, lastBuildSuccess, "2 minutes 20 seconds", 4, null); } public static Element createModsElement(int numMods) { Element modificationsElement = new Element("modifications"); for (int i = 1; i <= numMods; i++) { Element modificationElement = new Element("modification"); Element dateElement = new Element("date"); dateElement.addContent("10/30/2004 13:00:03"); // Put in dynamic value? modificationElement.addContent(dateElement); Element commentElement = new Element("comment"); commentElement.addContent("The comment"); modificationElement.addContent(commentElement); Element revisionElement = new Element("revision"); revisionElement.addContent("1." + i); modificationElement.addContent(revisionElement); Element fileElement = new Element("file"); fileElement.setAttribute("action", "modified"); Element revision2 = new Element("revision"); revision2.addContent("1." + i); fileElement.addContent(revision2); Element fileName = new Element("filename"); fileName.addContent("filename" + i); fileElement.addContent(fileName); modificationElement.addContent(fileElement); if (i != 1) { Element projectElement = new Element("project"); projectElement.addContent("basedir/subdirectory" + i); fileElement.addContent(projectElement); } Element userElement = new Element("user"); int userNumber = (i > 2) ? i - 1 : i; userElement.addContent("user" + userNumber); modificationElement.addContent(userElement); modificationsElement.addContent(modificationElement); } return modificationsElement; } public static Element createElement( boolean success, boolean lastBuildSuccess, String time, int modCount, String failureReason) { Element cruisecontrolElement = new Element("cruisecontrol"); Element buildElement = new Element("build"); buildElement.setAttribute("time", time); if (!success) { buildElement.setAttribute( "error", (failureReason == null) ? "Compile failed" : failureReason); } cruisecontrolElement.addContent(createModsElement(modCount)); cruisecontrolElement.addContent(buildElement); cruisecontrolElement.addContent( createInfoElement("somelabel", lastBuildSuccess)); Document doc = new Document(); doc.setRootElement(cruisecontrolElement); return cruisecontrolElement; } public static Element createInfoElement(String label, boolean lastSuccessful) { Element info = new Element("info"); addProperty(info, "projectname", "someproject"); addProperty(info, "label", label); addProperty(info, "lastbuildtime", ""); addProperty(info, "lastgoodbuildtime", ""); addProperty(info, "lastbuildsuccessful", lastSuccessful + ""); addProperty(info, "buildfile", ""); addProperty(info, "builddate", "11/30/2005 12:07:27"); addProperty(info, "target", ""); addProperty(info, "logfile", "log20020313120000.xml"); addProperty(info, "cctimestamp", "20020313120000"); return info; } /** * Return true when same. * @param msg error message prefix * @param refarr first array * @param testarr second array */ public static void assertArray(final String msg, final Object[] refarr, final Object[] testarr) { Assert.assertNotNull(refarr); Assert.assertNotNull(testarr); Assert.assertNotNull(msg + " Reference array is null and test not", refarr); Assert.assertNotNull(msg + " Test array is null and reference not", testarr); int shorterLength = Math.min(refarr.length, testarr.length); for (int i = 0; i < shorterLength; i++) { Assert.assertEquals(msg + " Element " + i + " mismatch.", refarr[i], testarr[i]); } Assert.assertEquals(msg + " Arrays have different lengths", refarr.length, testarr.length); Assert.assertEquals(msg, Arrays.asList(refarr), Arrays.asList(testarr)); } public static void addProperty(Element e, String name, String value) { Element prop = new Element("property"); prop.setAttribute("name", name); prop.setAttribute("value", value); e.addContent(prop); } }