/******************************************************************************** * 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.web.command; import java.util.Collection; import java.util.HashMap; import java.util.Map; import net.sourceforge.cruisecontrol.dashboard.Build; import net.sourceforge.cruisecontrol.dashboard.BuildDetail; import net.sourceforge.cruisecontrol.dashboard.BuildSummary; import net.sourceforge.cruisecontrol.dashboard.CurrentStatus; import net.sourceforge.cruisecontrol.dashboard.LogFile; import net.sourceforge.cruisecontrol.dashboard.PreviousResult; import net.sourceforge.cruisecontrol.dashboard.testhelpers.DataUtils; import net.sourceforge.cruisecontrol.dashboard.utils.CCDateFormatter; import org.apache.commons.lang.StringUtils; import org.jmock.Mock; import org.jmock.cglib.MockObjectTestCase; import org.joda.time.DateTime; public class BuildCommandTest extends MockObjectTestCase { private LogFile logFile; private LogFile passedLogFile; protected void setUp() throws Exception { super.setUp(); logFile = new LogFile("log19991212050505.xml"); passedLogFile = new LogFile("log19991212050505Lbuild.9.xml"); } public void testBuildCommandShouldTakeBuildAsContructor() { Map props = new HashMap(); props.put("projectname", "project 1"); BuildDetail build = new BuildDetail(logFile, props); BuildCommand command = new BuildCommand(build, null); assertEquals("project 1", command.getBuild().getProjectName()); assertFalse(command.getBuild().hasPassed()); } public void testShouldReturnClassNameAsLongFailedWhenBuildIsMoreThanFailed24HoursAgo() { BuildDetail build = new BuildDetail(logFile); BuildCommand command = new BuildCommand(build, null); BuildSummary buildSummary = new BuildSummary("", PreviousResult.PASSED, DataUtils.PASSING_BUILD_LBUILD_0_XML); command.updateCssLevel(buildSummary); assertEquals("8", command.getLevel()); } public void testShouldReturnClassNameAsFailedWhenBuildIsLessThanFailed24HoursAgo() { BuildDetail build = new BuildDetail(logFile); BuildCommand command = new BuildCommand(build, null); String logFileName = "log" + CCDateFormatter.yyyyMMddHHmmss(new DateTime()) + ".xml"; BuildSummary buildSummary = new BuildSummary("", PreviousResult.PASSED, logFileName); command.updateCssLevel(buildSummary); assertEquals("0", command.getLevel()); } public void testShouldReturnClassNameAsFailedWhenBuildNeverPassed() { BuildDetail build = new BuildDetail(new LogFile("log20051209122103.xml")); BuildCommand command = new BuildCommand(build, null); command.updateCssLevel(null); assertEquals("8", command.getLevel()); } public void testCassNameShouldBeLevel8WhenTheLatestSuccessfulBuildIs24HoursAgo() throws Exception { BuildDetail build = new BuildDetail(passedLogFile); BuildCommand buildCommand = new BuildCommand(build, null); DateTime buildDate = new DateTime().minusYears(2); String logFileName = "log" + CCDateFormatter.yyyyMMddHHmmss(buildDate) + ".xml"; BuildSummary buildSummary = new BuildSummary("", PreviousResult.PASSED, logFileName); buildCommand.updateCssLevel(buildSummary); assertEquals("8", buildCommand.getLevel()); } public void testShouldBeAbleToDelegateTheInvocationToBuildSummary() throws Exception { Build summary = new BuildSummary("project1", PreviousResult.PASSED, DataUtils.PASSING_BUILD_LBUILD_0_XML); BuildCommand command = new BuildCommand(summary, null); assertEquals("project1", command.getBuild().getProjectName()); } public void testCalculatesElapsedBuildTime() throws Exception { Mock mockBuildSummary = mock(BuildSummary.class, new Class[]{String.class}, new Object[]{""}); BuildCommand command = new BuildCommand((Build) mockBuildSummary.proxy(), null); DateTime fivePM = CCDateFormatter.format("2007-04-20 17:00:00", "yyyy-MM-dd HH:mm:ss"); mockBuildSummary.expects(once()).method("getBuildingSince").will(returnValue(fivePM)); DateTime sixPM = CCDateFormatter.format("2007-04-20 18:00:00", "yyyy-MM-dd HH:mm:ss"); Long elapsedSeconds = command.getElapsedTimeBuilding(sixPM); assertEquals(new Long(3600), elapsedSeconds); } public void testShouldClassNameAsDarkRedWhenBuildIsFailed24HoursAgo() { Build buildSummary = new BuildSummary("", PreviousResult.FAILED, DataUtils.FAILING_BUILD_XML); Build lastSuccessful = new BuildSummary("", PreviousResult.PASSED, DataUtils.PASSING_BUILD_LBUILD_0_XML); BuildCommand command = new BuildCommand(buildSummary, null); command.updateCssLevel(lastSuccessful); assertEquals("8", command.toJsonHash().get(BuildCommand.CSS_LEVEL)); } public void testJsonHashShouldNotReturnDarkRedWhenBuildIsPassed() { BuildSummary buildSummary = new BuildSummary("", PreviousResult.PASSED, DataUtils.PASSING_BUILD_LBUILD_0_XML); buildSummary.updateStatus(CurrentStatus.WAITING.getCruiseStatus()); BuildCommand command = new BuildCommand(buildSummary, null); BuildSummary lastSuccessful = new BuildSummary("", PreviousResult.PASSED, DataUtils.PASSING_BUILD_LBUILD_0_XML); command.updateCssLevel(lastSuccessful); Map json = command.toJsonHash(); assertEquals("8", json.get(BuildCommand.CSS_LEVEL)); assertEquals(PreviousResult.PASSED.getStatus(), json.get("previous_result")); assertEquals(CurrentStatus.WAITING.getStatus(), json.get("current_status")); String jsonString = command.toJsonString(); assertJsonContains(jsonString, BuildCommand.CSS_LEVEL, "8"); assertJsonContains(jsonString, "previous_result", PreviousResult.PASSED.getStatus()); assertJsonContains(jsonString, "current_status", CurrentStatus.WAITING.getStatus()); } public void testJsonHashShouldNotReturnCurrentStatusWhenLastSuccessfulBuildIsEmpty() { BuildSummary buildSummary = new BuildSummary("", PreviousResult.FAILED, DataUtils.FAILING_BUILD_XML); buildSummary.updateStatus(CurrentStatus.WAITING.getCruiseStatus()); BuildCommand command = new BuildCommand(buildSummary, null); command.updateCssLevel(null); Map json = command.toJsonHash(); assertEquals("8", json.get(BuildCommand.CSS_LEVEL)); assertEquals(PreviousResult.FAILED.getStatus(), json.get("previous_result")); assertEquals("Waiting", json.get("current_status")); String jsonString = command.toJsonString(); assertJsonContains(jsonString, BuildCommand.CSS_LEVEL, "8"); assertJsonContains(jsonString, "previous_result", PreviousResult.FAILED.getStatus()); assertJsonContains(jsonString, "current_status", CurrentStatus.WAITING.getStatus()); } public void testJsonHashShouldReturnBuildSinceForActiveBuild() throws Exception { BuildSummary buildSummary = new BuildSummary("", PreviousResult.FAILED, DataUtils.FAILING_BUILD_XML); buildSummary.updateStatus("now building"); buildSummary.updateBuildSince(new DateTime()); BuildCommand command = new BuildCommand(buildSummary, null); Map json = command.toJsonHash(); assertTrue(json.containsKey("latest_build_date")); assertEquals(PreviousResult.FAILED.getStatus(), json.get("previous_result")); assertEquals("Building", json.get("current_status")); String jsonString = command.toJsonString(); assertJsonContains(jsonString, "previous_result", PreviousResult.FAILED.getStatus()); assertJsonContains(jsonString, "current_status", CurrentStatus.BUILDING.getStatus()); } public void testJsonHashShouldReturnLowerCaseOfStatusWhenInvokeDetaultCss() throws Exception { BuildSummary buildSummary = new BuildSummary("", PreviousResult.UNKNOWN, DataUtils.FAILING_BUILD_XML); buildSummary.updateStatus(CurrentStatus.WAITING.getCruiseStatus()); BuildCommand command = new BuildCommand(buildSummary, null); Map json = command.toJsonHash(); assertTrue(json.containsKey("latest_build_date")); assertEquals(PreviousResult.UNKNOWN.getStatus(), json.get("previous_result")); assertEquals(CurrentStatus.WAITING.getStatus(), json.get("current_status")); String jsonString = command.toJsonString(); assertJsonContains(jsonString, "previous_result", PreviousResult.UNKNOWN.getStatus()); assertJsonContains(jsonString, "current_status", CurrentStatus.WAITING.getStatus()); } public void testJsonHashShouldNotReturnBuildSinceForNonActiveBuild() throws Exception { BuildSummary buildSummary = new BuildSummary("", PreviousResult.FAILED, DataUtils.FAILING_BUILD_XML); buildSummary.updateStatus(CurrentStatus.DISCONTINUED.getCruiseStatus()); BuildCommand command = new BuildCommand(buildSummary, null); Map json = command.toJsonHash(); assertTrue(json.containsKey("latest_build_date")); assertEquals(PreviousResult.FAILED.getStatus(), json.get("previous_result")); assertEquals(CurrentStatus.DISCONTINUED.getStatus(), json.get("current_status")); String jsonString = command.toJsonString(); assertJsonContains(jsonString, "previous_result", PreviousResult.FAILED.getStatus()); assertJsonContains(jsonString, "current_status", CurrentStatus.DISCONTINUED.getStatus()); } public void testShouldReturnUnknownIfDurationIsNull() throws Exception { Mock build = mock(Build.class); build.expects(atLeastOnce()).method("getDuration").will(returnValue(null)); BuildCommand command = new BuildCommand((Build) build.proxy(), null); assertEquals("Unknown", command.getDuration()); } public void testShouldReturnEmptyCollectionWhenNoModificationsAvailableFromLogFile() throws Exception { Mock build = mock(Build.class); build.expects(atLeastOnce()).method("getModifications").will(returnValue(null)); BuildCommand command = new BuildCommand((Build) build.proxy(), null); final Collection modifications = command.getModifications(); assertTrue("Modifications should be empty", modifications.isEmpty()); } private void assertJsonContains(String jsonString, String key, String value) { assertTrue("Should contain \"" + key + "\" : \"" + value + "\" in\n" + jsonString, StringUtils .contains(jsonString, "\"" + key + "\" : \"" + value + "\"")); } }