package net.sourceforge.cruisecontrol;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.TestCase;
import net.sourceforge.cruisecontrol.config.FileResolver;
import net.sourceforge.cruisecontrol.config.XmlResolver;
import net.sourceforge.cruisecontrol.util.Util;
import org.jdom.Element;
public class CruiseControlConfigIncludeTest extends TestCase implements ResolverHolder {
private Element rootElement;
private Element includeElement;
private XmlResolver xmlResolver;
private FileResolver fileResolver;
protected void setUp() throws Exception {
final StringBuilder configText = new StringBuilder(200);
configText.append("<cruisecontrol>");
configText.append(" <plugin name='foo.project'");
configText.append(" classname='net.sourceforge.cruisecontrol.MockProjectInterface'/>");
configText.append(" <include.projects file='include.xml'/>");
configText.append(" <foo.project name='in.root'/>");
configText.append("</cruisecontrol>");
rootElement = elementFromString(configText.toString());
final StringBuilder includeText = new StringBuilder(200);
includeText.append("<cruisecontrol>");
includeText.append(" <foo.project name='in.include'/>");
includeText.append("</cruisecontrol>");
includeElement = elementFromString(includeText.toString());
xmlResolver = new IncludeXmlResolver(includeElement);
fileResolver = new EmptyFileResolver();
}
protected void tearDown() throws Exception {
rootElement = null;
includeElement = null;
xmlResolver = null;
}
public void testShouldLoadIncludedProjects() throws Exception {
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this, null);
assertEquals(2, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
assertIsFooProject(config.getProject("in.include"));
}
public void testShouldLoadedNestedIncludes() throws Exception {
final StringBuilder includeText = new StringBuilder(200);
includeText.append("<cruisecontrol>");
includeText.append(" <include.projects file='include.xml'/>");
includeText.append(" <foo.project name='in.first.include'/>");
includeText.append("</cruisecontrol>");
final Element includeWithNestedInclude = elementFromString(includeText.toString());
final Element[] elements = new Element[2];
elements[0] = includeWithNestedInclude;
elements[1] = includeElement;
xmlResolver = new IncludeXmlResolver(elements);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this, null);
assertEquals(3, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
assertIsFooProject(config.getProject("in.first.include"));
assertIsFooProject(config.getProject("in.include"));
}
public void testIncludesCanDefinePlugins() throws CruiseControlException {
final String newProjectTag = "new.project.type";
final Element pluginElement = new Element("plugin");
pluginElement.setAttribute("name", newProjectTag);
pluginElement.setAttribute("classname", MockProjectInterface.class.getName());
includeElement.addContent(pluginElement);
final Element barElement = new Element(newProjectTag);
barElement.setAttribute("name", "bar");
includeElement.addContent(barElement);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this, null);
assertEquals(3, config.getProjectNames().size());
assertIsFooProject(config.getProject("bar"));
}
public void testPropertiesShouldBeAvailableToIncludedProjects() throws CruiseControlException {
final Element property = new Element("property");
property.setAttribute("name", "baz");
property.setAttribute("value", "goo");
rootElement.addContent(property);
final Element project = new Element("foo.project");
project.setAttribute("name", "${baz}");
includeElement.addContent(project);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this);
assertEquals(3, config.getProjectNames().size());
assertIsFooProject(config.getProject("goo"));
}
public void testErrorsInIncludeShouldBeContained() throws CruiseControlException {
final Element unknownPlugin = new Element("unknown.plugin.error");
includeElement.addContent(unknownPlugin);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this);
assertEquals(1, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
}
public void testErrorsParsingIncludeShouldBeContained() throws CruiseControlException {
xmlResolver = new XmlResolver() {
public Element getElement(String path) throws CruiseControlException {
throw new CruiseControlException("simulate parse error");
}
};
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this);
assertEquals(1, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
}
public void testIncludeFilenameContainsProperty() throws CruiseControlException {
xmlResolver = new XmlResolver() {
private final Element includePropertyElement;
{
final StringBuilder includeText = new StringBuilder(200);
includeText.append("<cruisecontrol>");
includeText.append(" <foo.project name='in.include.withproperty'/>");
includeText.append("</cruisecontrol>");
includePropertyElement = elementFromString(includeText.toString());
}
public Element getElement(String path) throws CruiseControlException {
assertEquals("include_FOO_.xml", path);
return includePropertyElement;
}
};
final Element propertyElement = new Element("property");
propertyElement.setAttribute("name", "filenameswitch");
propertyElement.setAttribute("value", "_FOO_");
rootElement.addContent(propertyElement);
rootElement.removeChild("include.projects");
final Element includeTagElement = new Element("include.projects");
includeTagElement.setAttribute("file", "include${filenameswitch}.xml");
rootElement.addContent(includeTagElement);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this);
assertEquals(2, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
assertIsFooProject(config.getProject("in.include.withproperty"));
}
public void testIncludeFilenameContainsUnsetProperty() throws CruiseControlException {
xmlResolver = new XmlResolver() {
public Element getElement(String path) throws CruiseControlException {
throw new CruiseControlException("failed to load file []");
}
};
rootElement.removeChild("include.projects");
final Element includeTagElement = new Element("include.projects");
includeTagElement.setAttribute("file", "include${filenameswitch}.xml");
rootElement.addContent(includeTagElement);
final CruiseControlConfig config = new CruiseControlConfig(rootElement, this);
assertEquals(1, config.getProjectNames().size());
assertIsFooProject(config.getProject("in.root"));
}
public static Element elementFromString(final String text) throws CruiseControlException {
final InputStream is = new ByteArrayInputStream(text.getBytes());
return Util.loadRootElement(is);
}
public FileResolver getFileResolver() {
return fileResolver;
}
public XmlResolver getXmlResolver() {
return xmlResolver;
}
private void assertIsFooProject(final ProjectInterface project) {
assertNotNull(project);
assertEquals(MockProjectInterface.class.getName(), project.getClass().getName());
}
private class IncludeXmlResolver implements XmlResolver {
private final Element[] includeElements;
private int count = 0;
IncludeXmlResolver(final Element element) {
includeElements = new Element[] {element};
}
IncludeXmlResolver(final Element[] elements) {
includeElements = elements;
}
public Element getElement(final String path) throws CruiseControlException {
assertEquals("include.xml", path);
final Element element = includeElements[count];
count++;
return element;
}
}
private class EmptyFileResolver implements FileResolver {
public InputStream getInputStream(final String path)
throws CruiseControlException {
// FIXME add correct implementation, if required!
throw new CruiseControlException("Method not implemented yet! Fix it!");
}
}
}