/******************************************************************************** * 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.dashboard; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.sourceforge.cruisecontrol.dashboard.testhelpers.FilesystemUtils; import net.sourceforge.cruisecontrol.dashboard.utils.TimeConverter; import org.apache.commons.io.FileUtils; import org.jmock.Mock; import org.jmock.cglib.MockObjectTestCase; public class BuildDetailTest extends MockObjectTestCase { private BuildDetail build; private LogFile defaultLogFile; protected void setUp() { defaultLogFile = new LogFile("log20051209122103.xml"); build = new BuildDetail(defaultLogFile); } public void testShouldBeComparedByDate() { BuildDetail laterBuild = new BuildDetail(new LogFile("log21111209122103.xml")); assertEquals(0, build.compareTo(build)); assertEquals(-1, build.compareTo(laterBuild)); assertEquals(1, laterBuild.compareTo(build)); } public void testCanGetNumberOfTestsFromBuild() { BuildTestSuite suiteWithFiveTests = new BuildTestSuite("", 0.0f); suiteWithFiveTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFiveTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFiveTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFiveTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFiveTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); BuildTestSuite suiteWithFourTests = new BuildTestSuite("", 0.0f); suiteWithFourTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFourTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFourTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); suiteWithFourTests.addTestCase(new BuildTestCase(null, null, null, null, null, null)); List nineTests = new ArrayList(); nineTests.add(suiteWithFiveTests); nineTests.add(suiteWithFourTests); Map props = new HashMap(); props.put("testsuites", nineTests); BuildDetail laterBuild = new BuildDetail(defaultLogFile, props); assertEquals(9, laterBuild.getNumberOfTests()); } public void testCanGetNumberOfFailedTests() { BuildTestSuite suiteWithTwoFailures = new BuildTestSuite("", 0.0f); suiteWithTwoFailures.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.FAILED)); suiteWithTwoFailures.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.FAILED)); BuildTestSuite suiteWithOneFailure = new BuildTestSuite("", 0.0f); suiteWithOneFailure.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.FAILED)); List threeFailures = new ArrayList(); threeFailures.add(suiteWithTwoFailures); threeFailures.add(suiteWithOneFailure); Map props = new HashMap(); props.put("testsuites", threeFailures); BuildDetail laterBuild = new BuildDetail(defaultLogFile, props); assertEquals(3, laterBuild.getNumberOfFailures()); } public void testCanGetNumberOfTestErrors() { BuildTestSuite suiteWithTwoErrors = new BuildTestSuite("", 0.0f); suiteWithTwoErrors.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.ERROR)); suiteWithTwoErrors.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.ERROR)); BuildTestSuite suiteWithThreeErrors = new BuildTestSuite("", 0.0f); suiteWithThreeErrors.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.ERROR)); suiteWithThreeErrors.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.ERROR)); suiteWithThreeErrors.addTestCase(new BuildTestCase(null, null, null, null, null, BuildTestCaseResult.ERROR)); List fiveErrors = new ArrayList(); fiveErrors.add(suiteWithTwoErrors); fiveErrors.add(suiteWithThreeErrors); Map props = new HashMap(); props.put("testsuites", fiveErrors); BuildDetail laterBuild = new BuildDetail(defaultLogFile, props); assertEquals(5, laterBuild.getNumberOfErrors()); } public void testShouldReturnPassedAsStringWhenTheBuildPassed() { LogFile laterLogFile = new LogFile("log20001212050505Lbuild.2.xml"); BuildDetail laterBuild = new BuildDetail(laterLogFile); assertEquals(PreviousResult.PASSED, laterBuild.getPreviousBuildResult()); } public void testShouldReturnPassedAsStringWhenTheBuildFailed() { LogFile laterLogFile = new LogFile("log20001212050505.xml"); BuildDetail laterBuild = new BuildDetail(laterLogFile); assertEquals(PreviousResult.FAILED, laterBuild.getPreviousBuildResult()); } public void testPluginOutputShouldBeInOrder() throws Exception { build.addPluginOutput("cate2", "out1"); build.addPluginOutput("cate1", "out1"); build.addPluginOutput("cate3", "out1"); Iterator iterator = build.getPluginOutputs().keySet().iterator(); assertEquals("cate2", (String) iterator.next()); assertEquals("cate1", (String) iterator.next()); assertEquals("cate3", (String) iterator.next()); } public void testShouldReturnAllArtifactsForTheBuild() throws Exception { String projectName = "p1"; String timeStamp = "20001212050505"; File artifactsRoot = FilesystemUtils.createDirectory(projectName); File artifactsDir = FilesystemUtils.createDirectory(timeStamp, projectName); FilesystemUtils.createFile("p1.jar", artifactsDir); FilesystemUtils.createFile("p1.war", artifactsDir); FilesystemUtils.createFile("p1.ear", artifactsDir); Map props = new HashMap(); LogFile logFile = new LogFile("log20001212050505.xml"); props.put("artifactfolder", artifactsRoot); final BuildDetail detail = new BuildDetail(logFile, props); assertEquals(getErrMsgTimeZone(timeStamp, detail), 3, detail.getArtifactFiles().size()); } private static String getErrMsgTimeZone(final String timeStamp, final BuildDetail detail) { return "This test failure could be a JVM TimeZone issue: " + "\ntimestamp: " + timeStamp + "; \nBuildDetail.getTimeStamp(): " + detail.getTimeStamp() + "; \nBuildDetail.getBuildDate(): " + detail.getBuildDate().toString( org.joda.time.format.DateTimeFormat.forPattern("yyyyMMddHHmmss")) + "; \nDo you see the extra/missing '5' above?" + "; \nJoda TimeZone: " + org.joda.time.DateTimeZone.getDefault() + "; \nIs Joda TimeZone above what you'd expect? Does it match your OS setting?" + "; \nsee: http://www.mail-archive.com/joda-interest@lists.sourceforge.net/msg01073.html\n"; } public void testShouldGetArtifactsInSubDirectories() throws Exception { String projectName = "p2"; String timeStamp = "20001212050505"; File artifactsRoot = FilesystemUtils.createDirectory(projectName); File artifactsDir = FilesystemUtils.createDirectory(timeStamp, projectName); FilesystemUtils.createFile("p2.jar", artifactsDir); FilesystemUtils.createFile("p2.war", artifactsDir); FilesystemUtils.createFile("p2.ear", artifactsDir); File subDir = new File(artifactsDir, "subdir"); FileUtils.forceMkdir(subDir); FilesystemUtils.createFile("p3.ear", subDir); FilesystemUtils.createFile("p4.ear", subDir); Map props = new HashMap(); LogFile logFile = new LogFile("log20001212050505.xml"); props.put("artifactfolder", artifactsRoot); final BuildDetail detail = new BuildDetail(logFile, props); List artifactNames = toFileNameList(detail.getArtifactFiles()); assertEquals(getErrMsgTimeZone(timeStamp, detail), 4, artifactNames.size()); assertTrue(artifactNames.contains("p2.war")); assertTrue(artifactNames.contains("p2.jar")); assertTrue(artifactNames.contains("p2.ear")); assertTrue(artifactNames.contains("subdir")); } private List toFileNameList(final List files) { final List fileNames = new ArrayList(); for (Object fileObj : files) { final File file = (File) fileObj; fileNames.add(file.getName()); } return fileNames; } public void testShouldInvokeTheTimeConverter() throws Exception { Mock timeConverterMock = mock(TimeConverter.class); BuildDetail laterBuild = new BuildDetail(new LogFile("log21111209122103.xml"), new HashMap(), (TimeConverter) timeConverterMock.proxy()); timeConverterMock.expects(once()).method("getConvertedTime"); laterBuild.getConvertedTime(); } }