/*******************************************************************************
* Copyright (c) 2004, 2008 Spring IDE Developers
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.test;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.core.IBeansProjectMarker;
import org.springframework.ide.eclipse.beans.core.internal.model.BeansConfigSet;
import org.springframework.ide.eclipse.beans.core.internal.model.BeansProject;
import org.springframework.ide.eclipse.beans.core.model.IBeansConfig;
import org.springframework.ide.eclipse.beans.core.model.IBeansConfigSet;
import org.springframework.ide.eclipse.beans.core.model.IBeansModel;
import org.springframework.ide.eclipse.core.SpringCore;
import org.springframework.ide.eclipse.core.SpringCoreUtils;
import org.springframework.ide.eclipse.core.java.JdtUtils;
/**
* this class tests the config file validator. The test method is to create a
* config file with certain expected errors, and check the validation creates
* the expected error markers
* @author Loren Rosen
* @author Torsten Juergeleit
* @author Christian Dupuis
*/
public class ValidationTests extends AbstractSpringIdeTest {
public ValidationTests(String name) {
super(name);
}
protected String xmlTestFileName = "sample.xml";
protected static String SimpleBeanText = "public class SimpleBean {"
+ "private String stuff;"
+ "public String getStuff() {return stuff;}"
+ "public void setStuff(String value) {this.stuff=value;}}";
protected static String ConstructedBeanText = "public class ConstructedBean {"
+ "private String stuff;"
+ "public ConstructedBean(String stuff, String more, String evenMore) { this.stuff = stuff;}"
+ "public String getStuff() {return stuff;}"
+ "public void setStuff(String value) {this.stuff=value;}}";
/**
* create the Java files used by the tests
*
* @throws Exception
*/
private void createBeanClasses() throws Exception {
IPackageFragment pack = project.createPackage("pack1");
project.createType(pack, "SimpleBean.java", SimpleBeanText);
project.createType(pack, "ConstructedBean.java", ConstructedBeanText);
project.waitForAutoBuild();
}
private void renameBeanClassProperty() throws Exception {
IType type = JdtUtils.getJavaType(project.getProject(),
"pack1.SimpleBean");
IMethod[] methods = type.getMethods();
for (int i = 0; i < methods.length; i++) {
IMethod method = methods[i];
if ("setStuff".equals(method.getElementName())) {
method.rename("setStuf", false, null);
}
}
}
public void testValidationErrors() throws Exception {
createBeanClasses();
BeansProject beansProject = createBeansProject();
IFile xmlFile = createXmlFile("sample.xml", beansProject);
IMarker[] markers = getFailureMarkers();
assertEquals("Wrong number of validation errors (problem markers)", 5,
markers.length);
// test that we get an error for a bean class
// that isn't in the class path
IMarker marker = markers[0];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(6, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"Class 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' not found",
marker.getAttribute(IMarker.MESSAGE, ""));
// test that we get an error for a bean class
// that isn't in the class path -- this time
// the class has a simple name (not qualifed with
// some other package)
marker = markers[1];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(10, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals("Class 'absent' not found", marker.getAttribute(
IMarker.MESSAGE, ""));
// test that we get an error for a bean class
// which tried to set an non-existent property
marker = markers[2];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(16, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"No setter for property 'absentProperty' found in class 'pack1.SimpleBean'",
marker.getAttribute(IMarker.MESSAGE, ""));
// test that we get an error for a child bean
// whose parent doesn't exist
marker = markers[3];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(20, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals("Undefined parent root bean", marker.getAttribute(
IMarker.MESSAGE, ""));
// test that we get an error for a bean
// that has no parent or class
marker = markers[4];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(23, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals("Bean definition has neither 'class' nor 'parent'", marker
.getAttribute(IMarker.MESSAGE, ""));
// test that we get an error for a bean
// that calls the bean constructor with the wrong
// number of arguments.
marker = markers[5];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(25, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"No constructor with 1 argument defined in class 'pack1.ConstructedBean'",
marker.getAttribute(IMarker.MESSAGE, ""));
marker = markers[6];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(30, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"No constructor with 2 arguments defined in class 'pack1.ConstructedBean'",
marker.getAttribute(IMarker.MESSAGE, ""));
renameBeanClassProperty();
project.waitForAutoBuild();
markers = getFailureMarkers();
assertEquals("Wrong number of validation errors (problem markers)", 8,
markers.length);
}
public void testParseErrors() throws Exception {
BeansProject beansProject = createBeansProject();
IFile xmlFile = createXmlFile("parseError.xml", beansProject);
IMarker[] markers = getFailureMarkers(xmlFile);
assertEquals(1, markers.length);
// test that we get an error for an XML
// parsing problem
IMarker marker = markers[0];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(6, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"Attribute \"undefinedAttribute\" must be declared for element type \"bean\".",
marker.getAttribute(IMarker.MESSAGE, ""));
}
public void testValidateConfigSetErrors() throws Exception {
createBeanClasses();
BeansProject beansProject = createBeansProject();
IFolder xmlFolder = project.createXmlFolder();
// TODO: try to create the xml folder only once per test
IFile xmlFileA = createXmlFile("a.xml", beansProject);
IFile xmlFileB = createXmlFile("b.xml", beansProject);
Set<String> configNames = new HashSet<String>();
configNames.add("xml/a.xml");
configNames.add("xml/b.xml");
BeansConfigSet b = new BeansConfigSet(beansProject, "configSet",
configNames, IBeansConfigSet.Type.MANUAL);
b.setAllowBeanDefinitionOverriding(false);
// TODO: really should run this test twice, with this flag set and unset
Collection c = beansProject.getConfigSets();
Set<IBeansConfigSet> l = new HashSet<IBeansConfigSet>();
l.add(b);
beansProject.setConfigSets(l);
beansProject.saveDescription();
updateTestFile(xmlFolder, "b.xml");
project.waitForAutoBuild();
IMarker[] markers = getFailureMarkers(xmlFileB);
assertEquals(1, markers.length);
// test that we get an error where one
// bean overrides another in a config set
IMarker marker = markers[0];
assertEquals(marker.getType(), IBeansProjectMarker.PROBLEM_MARKER);
assertEquals(6, marker.getAttribute(IMarker.LINE_NUMBER, 0));
assertEquals(
"Overrides another bean named 'simple' in config set 'configSet'",
marker.getAttribute(IMarker.MESSAGE, ""));
}
private BeansProject createBeansProject() throws CoreException {
IProject eclipseProject = project.getProject();
SpringCoreUtils.addProjectNature(eclipseProject, SpringCore.NATURE_ID,
new NullProgressMonitor());
project.waitForAutoBuild();
IBeansModel model = BeansCorePlugin.getModel();
BeansProject beansProject = (BeansProject) model
.getProject(eclipseProject);
assertNotNull("No sample project in model", beansProject);
return beansProject;
}
private IFile createXmlFile(String name, BeansProject beansProject)
throws CoreException, Exception {
// System.out.println("enter createXmlFile");
IFolder xmlFolder = project.createXmlFolder();
IFile xmlFile = createEmptyFile(xmlFolder, name);
assertTrue(xmlFile.getLocation().toFile().exists());
// BeansProject beansProject = createBeansProject();
beansProject.addConfig(xmlFile, IBeansConfig.Type.MANUAL);
project.waitForAutoBuild();
IBeansConfig beansConfig = beansProject.getConfig(xmlFile);
assertNotNull("No sample config in model", beansConfig);
// there's an apparent bug whereby the validation
// of the xml file isn't done when the file is added
// to the list of config files, but only after the
// file is modified. So we don't bother to put anything
// into the file until now.
updateTestFile(xmlFolder, name);
project.waitForAutoBuild();
return xmlFile;
}
/**
* create an empty file with the indicated name in the indicated folder
*
* @param destFolder the folder in which to create the file
* @param name the name of the file to be created
* @return an eclipse handle on the newly created file
* @throws CoreException
*/
protected IFile createEmptyFile(IFolder destFolder, String name)
throws CoreException {
IFile destFile = destFolder.getFile(name);
byte[] buf = new byte[] {};
InputStream stream = new ByteArrayInputStream(buf);
destFile.create(stream, false, null);
return destFile;
}
/**
* copy the test data file from the plugin source area into the workspace
* being tested, in the indicated folder. return a handle on the newly
* created file
*/
protected IFile copyTestFile(IFolder destFolder, String name)
throws Exception {
IFile destFile = destFolder.getFile(name);
String sourceName = getSourceDataPath() + java.io.File.separator + name;
InputStream stream = new FileInputStream(sourceName);
destFile.create(stream, false, null);
return destFile;
}
/**
* update the test data file, which is in the indicated folder, using the
* file of the same name from the plugin source area. return a handle on the
* newly created file
*/
protected IFile updateTestFile(IFolder destFolder, String name)
throws Exception {
IFile destFile = destFolder.getFile(name);
String sourceName = getSourceDataPath() + java.io.File.separator + name;
InputStream stream = new FileInputStream(sourceName);
destFile.setContents(stream, false, false, null);
return destFile;
}
/**
* @return the path to the root of the source for this plugin
*/
protected String getPluginDirectoryPath() {
try {
URL platformURL = Platform.getBundle(
"org.springframework.ide.eclipse.test").getEntry("/");
return new File(Platform.asLocalURL(platformURL).getFile())
.getAbsolutePath();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @return the path to the data to be tested (text files which will be
* copied into the test area)
*/
public String getSourceDataPath() {
return getPluginDirectoryPath() + java.io.File.separator + "data";
}
/**
* Returns the failure markers for the workspace.
*/
private IMarker[] getFailureMarkers() throws CoreException {
return getFailureMarkers(ResourcesPlugin.getWorkspace().getRoot());
}
/**
* Returns the failure markers for given resource.
*/
private IMarker[] getFailureMarkers(IResource resource)
throws CoreException {
return resource.findMarkers(null, false, IResource.DEPTH_INFINITE);
}
}