/********************************************************************************
* 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.service;
import net.sourceforge.cruisecontrol.BuildLoopInformation;
import net.sourceforge.cruisecontrol.BuildLoopInformation.JmxInfo;
import net.sourceforge.cruisecontrol.BuildLoopInformation.ProjectInfo;
import net.sourceforge.cruisecontrol.Modification;
import net.sourceforge.cruisecontrol.dashboard.Projects;
import net.sourceforge.cruisecontrol.dashboard.repository.BuildInformationRepository;
import net.sourceforge.cruisecontrol.dashboard.repository.ClosableProjectMBeanConnection;
import net.sourceforge.cruisecontrol.dashboard.testhelpers.jmxstub.MBeanServerConnectionBuildOutputStub;
import net.sourceforge.cruisecontrol.dashboard.testhelpers.jmxstub.MBeanServerConnectionOutputIDStub;
import org.jmock.Mock;
import org.jmock.cglib.MockObjectTestCase;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class BuildLoopQueryServiceTest extends MockObjectTestCase {
private static final String PROJECT_NAME = "connectfour";
private BuildLoopQueryService buildLoopQueryService;
private Mock envService;
private Mock repository;
private Mock projectInfo;
private Mock closableProjectMBeanConnection;
protected void setUp() throws Exception {
envService = mock(EnvironmentService.class,
new Class[]{DashboardConfigService[].class},
new Object[]{null});
repository = mock(BuildInformationRepository.class);
projectInfo = mock(BuildLoopInformation.ProjectInfo.class,
new Class[]{String.class, String.class, String.class},
new Object[]{null, null, null});
buildLoopQueryService = new BuildLoopQueryService(
(EnvironmentService) envService.proxy(),
(BuildInformationRepository) repository.proxy());
closableProjectMBeanConnection = mock(ClosableProjectMBeanConnection.class);
}
public void testShouldReturnArrayContainsCommiterAndCommitMessage() throws Exception {
ArrayList modifications = new ArrayList();
Modification modification = new Modification("modification");
modification.userName = "committer";
modification.comment = "message 1";
modifications.add(modification);
projectInfo.expects(once()).method("getModifications").will(returnValue(modifications));
repository.expects(once()).method("getProjectInfo").with(eq(PROJECT_NAME)).will(
returnValue(projectInfo.proxy()));
List commitMessages = buildLoopQueryService.getCommitMessages(PROJECT_NAME);
assertEquals(1, commitMessages.size());
Modification message = (Modification) commitMessages.get(0);
assertEquals("modification", message.type);
assertEquals("committer", message.userName);
assertEquals("message 1", message.comment);
}
public void testShouldReturnBuildOutput() throws Exception {
repository.expects(once()).method("getJmxConnection").
will(returnValue(closableProjectMBeanConnection.proxy()));
closableProjectMBeanConnection.expects(once()).method("getMBeanServerConnection").
will(returnValue(new MBeanServerConnectionBuildOutputStub()));
closableProjectMBeanConnection.expects(once()).method("close");
String[] output = buildLoopQueryService.getBuildOutput(PROJECT_NAME, 0);
assertEquals("Build Failed", output[0]);
assertEquals("Build Duration: 10s", output[1]);
}
public void testShouldReturnLiveOutputID() throws Exception {
repository.expects(once()).method("getJmxConnection").
will(returnValue(closableProjectMBeanConnection.proxy()));
closableProjectMBeanConnection.expects(once()).method("getMBeanServerConnection").
will(returnValue(new MBeanServerConnectionOutputIDStub()));
closableProjectMBeanConnection.expects(once()).method("close");
String outputID = buildLoopQueryService.getLiveOutputID(PROJECT_NAME);
assertEquals("LiveOutputID", outputID);
}
public void testShouldReturnStatusMapKeyedOnProjectName() throws Exception {
Mock buildloopinfoMock =
mock(
BuildLoopInformation.class, new Class[]{ProjectInfo[].class, JmxInfo.class,
String.class, String.class}, new Object[]{null, null, null, null});
repository.expects(once()).method("hasBuildLoopInfoFor").with(eq("project1")).will(returnValue(true));
repository.expects(once()).method("getBuildLoopInfo").with(eq("project1")).will(
returnValue(buildloopinfoMock.proxy()));
buildloopinfoMock.expects(once()).method("getServerName").will(returnValue("192.168.1.1"));
String serverName = buildLoopQueryService.getServerName("project1");
assertEquals("192.168.1.1", serverName);
}
public void testShouldReturnServerNameMapKeyedOnProjectName() throws Exception {
Mock projectInfo2 =
mock(
BuildLoopInformation.ProjectInfo.class, new Class[]{String.class, String.class,
String.class}, new Object[]{null, null, null});
ArrayList infos = new ArrayList();
projectInfo.expects(once()).method("getName").will(returnValue("project1"));
projectInfo.expects(once()).method("getStatus").will(returnValue("now building"));
infos.add(projectInfo.proxy());
projectInfo2.expects(once()).method("getName").will(returnValue("project2"));
projectInfo2.expects(once()).method("getStatus").will(returnValue("paused"));
infos.add(projectInfo2.proxy());
repository.expects(once()).method("getProjectInfos").will(returnValue(infos));
final Map<String, String> projectsStatus = buildLoopQueryService.getAllProjectsStatus();
assertEquals("now building", projectsStatus.get("project1"));
assertEquals("paused", projectsStatus.get("project2"));
}
public void testShouldThrowExceptionWhenForceBuildIsDisabled() throws Exception {
envService.expects(atLeastOnce()).method("isForceBuildEnabled").will(returnValue(false));
repository.expects(never()).method("getJmxConnection");
try {
buildLoopQueryService.forceBuild(PROJECT_NAME);
fail();
} catch (Exception e) {
// expected exception
}
}
public void testShouldReturnProjectsObject() throws Exception {
Mock projectInfo2 =
mock(
BuildLoopInformation.ProjectInfo.class, new Class[]{String.class, String.class,
String.class}, new Object[]{null, null, null});
ArrayList infos = new ArrayList();
projectInfo.expects(once()).method("getName").will(returnValue("project1"));
infos.add(projectInfo.proxy());
projectInfo2.expects(once()).method("getName").will(returnValue("project2"));
infos.add(projectInfo2.proxy());
Mock mockLogDir = mock(File.class, new Class[]{String.class}, new Object[]{"logs"});
envService.expects(once()).method("getLogDir").will(returnValue(mockLogDir.proxy()));
envService.expects(once()).method("getArtifactsDir").will(returnValue(new File("arts")));
repository.expects(once()).method("getProjectInfos").will(returnValue(infos));
Projects projects = buildLoopQueryService.getProjects();
assertEquals(2, projects.getProjectsRegistedInBuildLoop().length);
assertEquals(mockLogDir.proxy(), projects.getLogRoot());
}
public void testShouldProvideDefaultServerNameForUnknownProject() throws Exception {
repository.expects(once()).method("hasBuildLoopInfoFor").with(eq("project1")).will(returnValue(false));
assertEquals("No server name available", buildLoopQueryService.getServerName("project1"));
}
public void testShouldReturnMeaningfulErrorMessageWhenUnableToConnectToJmx() throws Exception {
Mock buildLoopInfo = mock(BuildLoopInformation.class,
new Class[]{ProjectInfo[].class, JmxInfo.class, String.class, String.class},
new Object[]{new ProjectInfo[]{}, null, null, null});
repository.expects(once()).method("getJmxConnection").with(eq("project1")).will(returnValue(null));
repository.expects(once()).method("hasBuildLoopInfoFor").with(eq("project1")).will(returnValue(true));
repository.expects(once()).method("getBuildLoopInfo").with(eq("project1"))
.will(returnValue(buildLoopInfo.proxy()));
buildLoopInfo.expects(once()).method("getServerName").will(returnValue("server1"));
assertEquals(" - Unable to connect to build loop at server1",
buildLoopQueryService.getBuildOutput("project1", 0)[0]);
}
}