/********************************************************************************
* 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;
import java.util.List;
import java.util.Map;
import net.sourceforge.cruisecontrol.dashboard.BuildDetail;
import net.sourceforge.cruisecontrol.dashboard.BuildTestCase;
import net.sourceforge.cruisecontrol.dashboard.BuildTestSuite;
import net.sourceforge.cruisecontrol.dashboard.utils.CCDateFormatter;
import net.sourceforge.cruisecontrol.dashboard.service.BuildService;
import net.sourceforge.cruisecontrol.dashboard.service.HistoricalBuildSummariesService;
import net.sourceforge.cruisecontrol.dashboard.service.BuildSummaryUIService;
import net.sourceforge.cruisecontrol.dashboard.service.ConfigurationService;
import net.sourceforge.cruisecontrol.dashboard.service.DashboardConfigFileFactory;
import net.sourceforge.cruisecontrol.dashboard.service.DashboardXmlConfigService;
import net.sourceforge.cruisecontrol.dashboard.service.SystemPropertyConfigService;
import net.sourceforge.cruisecontrol.dashboard.service.WidgetPluginService;
import net.sourceforge.cruisecontrol.dashboard.service.BuildLoopQueryService;
import net.sourceforge.cruisecontrol.dashboard.testhelpers.DataUtils;
import net.sourceforge.cruisecontrol.dashboard.testhelpers.jmxstub.BuildLoopQueryServiceStub;
import net.sourceforge.cruisecontrol.dashboard.web.command.BuildCommand;
import net.sourceforge.cruisecontrol.dashboard.widgets.Widget;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver;
public class BuildDetailControllerTest extends SpringBasedControllerTests {
private BuildDetailController controller;
private PropertiesMethodNameResolver projectDetailResolver;
protected void onControllerSetup() throws Exception {
System.setProperty(DashboardConfigFileFactory.PROPS_CC_DASHBOARD_CONFIG,
"test/data/dashboard-config.xml");
System.setProperty(BuildLoopQueryServiceStub.PROPS_CC_CONFIG_FILE, DataUtils.getConfigXmlAsFile()
.getAbsolutePath());
System.setProperty(SystemPropertyConfigService.PROPS_CC_CONFIG_ARTIFACTS_DIR, DataUtils
.getArtifactsDirAsFile().getAbsolutePath());
System.setProperty(SystemPropertyConfigService.PROPS_CC_CONFIG_LOG_DIR, DataUtils.getLogDirAsFile()
.getAbsolutePath());
super.onControllerSetup();
springConfigurationService().setDashboardConfigLocation(DataUtils.getConfigXmlAsFile().getAbsolutePath());
springDashboardXmlConfigService().afterPropertiesSet();
}
protected void onTearDown() throws Exception {
System.setProperty(DashboardConfigFileFactory.PROPS_CC_DASHBOARD_CONFIG, "");
}
public void setBuildDetailController(BuildDetailController controller) {
this.controller = controller;
}
private void prepareRequest(String name, String projectName) {
getRequest().setMethod("GET");
getRequest().setRequestURI("/build/detail/" + projectName + "/"
+ CCDateFormatter.getBuildDateFromLogFileName(name));
}
private BuildDetail getBuildDetail(BuildCommand buildCommand) {
return (BuildDetail) buildCommand.getBuild();
}
public void testShouldBeAbleToShowFailedTestCasesForFailedBuild() throws Exception {
prepareRequest(DataUtils.getFailedBuildLbuildAsFile().getName(), "project1");
ModelAndView mav = this.controller.handleRequest(getRequest(), getResponse());
BuildCommand buildCommand = (BuildCommand) mav.getModel().get("buildCmd");
BuildDetail build = getBuildDetail(buildCommand);
List suites = build.getTestSuites();
BuildTestSuite suite = (BuildTestSuite) suites.get(0);
assertEquals(DataUtils.TESTSUITE_IN_BUILD_LBUILD, suite.getName());
assertEquals(12, suite.getNumberOfTests());
assertEquals("Get wrong number of passed test cases.", 8, suite.getPassedTestCases().size());
assertEquals("Get wrong number of failed test cases.", 3, suite.getFailingTestCases().size());
BuildTestCase testCase = (BuildTestCase) suite.getFailingTestCases().get(0);
assertEquals("testSomething", testCase.getName());
assertEquals("3.807", testCase.getDuration());
assertEquals("net.sourceforge.cruisecontrol.sampleproject.connectfour.PlayingStandTest", testCase
.getClassname());
assertEquals("junit.framework.AssertionFailedError: Error during schema validation \n"
+ "\tat junit.framework.Assert.fail(Assert.java:47)", testCase.getMessageBody());
assertEquals(1, suite.getErrorTestCases().size());
testCase = (BuildTestCase) suite.getErrorTestCases().get(0);
assertEquals("testFourConnected", testCase.getName());
assertEquals("0.016", testCase.getDuration());
assertEquals("net.sourceforge.cruisecontrol.sampleproject.connectfour.PlayingStandTest", testCase
.getClassname());
assertEquals("java.lang.NoClassDefFoundError: org/objectweb/asm/CodeVisitor\n"
+ "\tat net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:165)", testCase
.getMessageBody());
}
public void testShouldBeAbleToFindArtifactsForSuccessfulBuildOfConfiguredProject() throws Exception {
prepareRequest(DataUtils.getPassingBuildLbuildAsFile().getName(), "project1");
ModelAndView mav = this.controller.handleRequest(getRequest(), getResponse());
assertEquals("page_build_detail", mav.getViewName());
BuildCommand buildCommand = (BuildCommand) mav.getModel().get("buildCmd");
BuildDetail build = getBuildDetail(buildCommand);
String artifacts = build.getArtifactFiles().toString();
assertEquals(build.getArtifactFiles().toString(), 3, build.getArtifactFiles().size());
assertTrue(StringUtils.contains(artifacts, "artifact1.txt"));
assertFalse(StringUtils.contains(artifacts, "artifact2.txt"));
assertTrue(StringUtils.contains(artifacts, "subdir"));
assertTrue(StringUtils.contains(artifacts, "coverage.xml"));
}
public void testShouldBeAbleToShowTheDurationBetweenSuccessfulBuild() throws Exception {
prepareRequest(DataUtils.getFailedBuildLbuildAsFile().getName(), "project1");
ModelAndView mav = this.controller.handleRequest(getRequest(), getResponse());
Map model = mav.getModel();
String buildDuration = (String) model.get("durationToSuccessfulBuild");
assertEquals("less than a minute ago", buildDuration);
}
public void testShouldBeAbleToShowFailedCheckStyleForFailedBuild() throws Exception {
prepareRequest(DataUtils.getFailedBuildLbuildAsFile().getName(), "project1");
ModelAndView mav = this.controller.handleRequest(getRequest(), getResponse());
BuildDetail build = getBuildDetail((BuildCommand) mav.getModel().get("buildCmd"));
String pluginOutput = (String) build.getPluginOutputs().get("Merged Check Style");
assertTrue(StringUtils.contains(pluginOutput, "Parser.java"));
}
public void setProjectDetailResolver(PropertiesMethodNameResolver resolver) {
this.projectDetailResolver = resolver;
}
public void testShouldBeAbleToInvokePluginOutputServiceStub() throws Exception {
prepareRequest(DataUtils.getFailedBuildLbuildAsFile().getName(), "project1");
BuildDetailController newController = createNewController(new WidgetPluginService(null) {
public void mergePluginOutput(BuildDetail build, Map parameters) {
build.addPluginOutput("checkstyle", "some thing got wrong");
}
});
newController.setMethodNameResolver(projectDetailResolver);
ModelAndView mav = newController.handleRequest(getRequest(), getResponse());
BuildDetail build = getBuildDetail((BuildCommand) mav.getModel().get("buildCmd"));
assertEquals("some thing got wrong", build.getPluginOutputs().get("checkstyle"));
}
public void testShouldPassWebContextRootToWidgets() throws Exception {
prepareRequest(DataUtils.getFailedBuildLbuildAsFile().getName(), "project1");
getRequest().setContextPath("any_new_context_path");
BuildDetailController newController = createNewController(new WidgetPluginService(null) {
public void mergePluginOutput(BuildDetail build, Map parameters) {
build.addPluginOutput("checkstyle", parameters.get(Widget.PARAM_WEB_CONTEXT_PATH));
}
});
newController.setMethodNameResolver(projectDetailResolver);
ModelAndView mav = newController.handleRequest(getRequest(), getResponse());
BuildDetail build = getBuildDetail((BuildCommand) mav.getModel().get("buildCmd"));
assertEquals("any_new_context_path", build.getPluginOutputs().get("checkstyle"));
}
private BuildDetailController createNewController(WidgetPluginService widgetPluginService) {
return new BuildDetailController(
springBuildService(),
springHistoricalBuildSummaryService(),
widgetPluginService,
springBuildSummaryUIService(),
springBuildLoopQueryService());
}
public void testShouldBeAbleToGetCheckstyleInfoAndMergeItToBuild() throws Exception {
prepareRequest("log20051209122103.xml", "project2");
ModelAndView mav = this.controller.handleRequest(getRequest(), getResponse());
BuildDetail build = getBuildDetail((BuildCommand) mav.getModel().get("buildCmd"));
assertTrue(StringUtils.contains((String) build.getPluginOutputs().get("Merged Check Style"), "Parser.java"));
}
private BuildSummaryUIService springBuildSummaryUIService() {
return (BuildSummaryUIService) this.applicationContext.getBean("buildSummaryUIService");
}
private BuildLoopQueryService springBuildLoopQueryService() {
return (BuildLoopQueryService) this.applicationContext.getBean("jmxServiceStub");
}
private DashboardXmlConfigService springDashboardXmlConfigService() {
return (DashboardXmlConfigService) this.applicationContext.getBean("dashboardXmlConfigService");
}
private BuildService springBuildService() {
return (BuildService) this.applicationContext.getBean("buildService");
}
private HistoricalBuildSummariesService springHistoricalBuildSummaryService() {
return (HistoricalBuildSummariesService) this.applicationContext.getBean("historicalBuildSummariesService");
}
private ConfigurationService springConfigurationService() {
return (ConfigurationService) this.applicationContext.getBean("configuration");
}
}