blob: ae78e6143cd45e7e770549d8bc7f694aa994f724 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xml.ui.tests;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.provisional.preferences.CommonEditorPreferenceNames;
import org.eclipse.wst.sse.ui.internal.reconcile.DocumentRegionProcessor;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorMetaData;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorStrategy;
/**
* Tests reconciler in an open editor. The location of this class is awkward
* in that it refers to content types declared in plugins that aren't required
* to be present.
*/
public class TestSourceValidationFramework extends TestCase {
/**
* THIS SUBCLASS IS FOR TESTING ONLY
*/
public static class TestStructuredTextEditor extends StructuredTextEditor {
public SourceViewerConfiguration textViewerConfiguration = null;
protected void setSourceViewerConfiguration(SourceViewerConfiguration config) {
super.setSourceViewerConfiguration(config);
textViewerConfiguration = config;
}
}
private static final String PROJECT_NAME = "TestSourceValidationFramework";
private static final String SEPARATOR = String.valueOf(IPath.SEPARATOR);
private boolean fPreviousReconcilerPref;
public TestSourceValidationFramework() {
super("TestSourceValidationFramework");
}
private IFile ensureFileIsAccessible(String filePath, byte[] contents) {
IFile blankFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(filePath));
if (blankFile != null && !blankFile.isAccessible()) {
try {
byte[] bytes = contents;
if (bytes == null) {
bytes = new byte[0];
}
blankFile.create(new ByteArrayInputStream(bytes), true, new NullProgressMonitor());
}
catch (CoreException e) {
e.printStackTrace();
}
}
return blankFile;
}
private IContentType[] detectContentTypes(String fileName) {
IContentType[] types = null;
IFile file = ensureFileIsAccessible(PROJECT_NAME + SEPARATOR + fileName, null);
types = Platform.getContentTypeManager().findContentTypesFor(file.getName());
if (types.length == 0) {
IContentDescription d = null;
try {
// optimized description lookup, might not succeed
d = file.getContentDescription();
if (d != null) {
types = new IContentType[]{d.getContentType()};
}
}
catch (CoreException e) {
/*
* should not be possible given the accessible and file type
* check above
*/
}
}
if (types == null) {
types = Platform.getContentTypeManager().findContentTypesFor(file.getName());
}
return types;
}
private String[] detectContentTypeIDs(String fileName) {
IContentType[] types = detectContentTypes(fileName);
String[] ids = new String[types.length];
for (int i = 0; i < types.length; i++) {
ids[i] = types[i].getId();
}
return ids;
}
private boolean identicalContents(Object o1[], Object o2[]) {
if (o1.length == 0 && o2.length == 0)
return true;
Object[] array1 = new Object[o1.length];
Object[] array2 = new Object[o2.length];
System.arraycopy(o1, 0, array1, 0, o1.length);
System.arraycopy(o2, 0, array2, 0, o2.length);
Arrays.sort(array1);
Arrays.sort(array2);
return Arrays.equals(array1, array2);
}
private void ensureProjectIsAccessible(String projName) {
IProjectDescription description = ResourcesPlugin.getWorkspace().newProjectDescription(projName);
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName);
try {
if (!project.exists())
project.create(description, new NullProgressMonitor());
if (!project.isAccessible())
project.open(new NullProgressMonitor());
}
catch (CoreException e) {
e.printStackTrace();
}
}
private List getSourceValidatorIDs(String fileName) throws Exception {
List validatorIds = new ArrayList(1);
IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page = workbenchWindow.getActivePage();
IFile file = ensureFileIsAccessible(PROJECT_NAME + SEPARATOR + fileName, null);
IEditorPart editor = IDE.openEditor(page, file, TestStructuredTextEditor.class.getName(), true);
ITextEditor textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
TestStructuredTextEditor testTextEditor = (TestStructuredTextEditor) textEditor;
IReconciler reconciler = testTextEditor.textViewerConfiguration.getReconciler(testTextEditor.getTextViewer());
assertNotNull(reconciler);
assertTrue("unexpected IReconciler implementation: " + reconciler.getClass(), reconciler instanceof DocumentRegionProcessor);
Class reconcilerClass = reconciler.getClass();
Method method = null;
while (reconcilerClass != Object.class && method == null) {
Method[] methods = reconcilerClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals("getValidatorStrategy")) {
method = methods[i];
}
}
reconcilerClass = reconcilerClass.getSuperclass();
}
assertNotNull("no getValidatorStrategy method found on " + reconciler.getClass(), method);
method.setAccessible(true);
ValidatorStrategy strategy = (ValidatorStrategy) method.invoke(reconciler, new Object[0]);
assertNotNull(strategy);
Field fMetaData = strategy.getClass().getDeclaredField("fMetaData");
assertNotNull("validator metadata field \"fMetaData\" not found on strategy " + strategy.getClass(), fMetaData);
fMetaData.setAccessible(true);
List metadata = (List) fMetaData.get(strategy);
assertNotNull(metadata);
for (int i = 0; i < metadata.size(); i++) {
validatorIds.add(((ValidatorMetaData) metadata.get(i)).getValidatorId());
}
page.closeEditor(editor, false);
return validatorIds;
}
protected void setUp() throws Exception {
ensureProjectIsAccessible(PROJECT_NAME);
// turn on reconciling
IPreferenceStore store = SSEUIPlugin.getDefault().getPreferenceStore();
fPreviousReconcilerPref = store.getBoolean(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS);
if (!fPreviousReconcilerPref) {
store.setValue(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS, true);
}
}
protected void tearDown() throws Exception {
// restore reconciling preference
IPreferenceStore store = SSEUIPlugin.getDefault().getPreferenceStore();
store.setValue(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS, fPreviousReconcilerPref);
}
public void testSourceValidationEnablementWithInheritedValidators() throws Exception {
Object[] xmlValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.xml").toArray();
assertTrue("No XML source validators found", xmlValidatorIDs.length > 0);
Object[] xml99ValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.xml99").toArray();
assertTrue("No XML99 source validators found", xml99ValidatorIDs.length > 0);
Arrays.sort(xmlValidatorIDs);
Arrays.sort(xml99ValidatorIDs);
assertEquals("validator lists should be the same length", xmlValidatorIDs.length, xml99ValidatorIDs.length);
for (int i = 0; i < xmlValidatorIDs.length; i++) {
assertEquals("validator IDs should be the same [" + i + "]", xmlValidatorIDs[i], xml99ValidatorIDs[i]);
}
}
public void testSourceValidationEnablementWithUniqueValidators() throws Exception {
String[] xmlContentTypes = detectContentTypeIDs("testValidatorConfigurations.xml");
String[] xsdContentTypes = detectContentTypeIDs("testValidatorConfigurations.xsd");
/*
* If the current configuration does not include a distinct XSD
* content type, skip the rest
*/
if (!identicalContents(xmlContentTypes, xsdContentTypes)) {
List xmlValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.xml");
assertTrue("No XML source validators found", !xmlValidatorIDs.isEmpty());
List xsdValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.xsd");
assertTrue("No XSD source validators found", !xsdValidatorIDs.isEmpty());
for (int i = 0; i < xmlValidatorIDs.size(); i++) {
assertTrue("XML Validator found on XSD input", !xsdValidatorIDs.contains(xmlValidatorIDs.get(i)));
}
}
else {
String message = "No distinct XSD content type found while running " + getClass().getName();
System.err.println(message);
Logger.log(Logger.WARNING, message);
}
}
public void testSourceValidationEnablementWithUnrelatedContentTypes() throws Exception {
String[] dtdContentTypes = detectContentTypeIDs("testValidatorConfigurations.dtd");
String[] jspContentTypes = detectContentTypeIDs("testValidatorConfigurations.jsp");
if (dtdContentTypes.length == 0) {
String message = "No DTD content type found while running " + getClass().getName();
System.err.println(message);
Logger.log(Logger.WARNING, message);
}
if (jspContentTypes.length == 0) {
String message = "No JSP content type found while running " + getClass().getName();
System.err.println(message);
Logger.log(Logger.WARNING, message);
}
if (dtdContentTypes.length > 0 && jspContentTypes.length > 0 && !identicalContents(dtdContentTypes, jspContentTypes)) {
List dtdValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.dtd");
assertTrue("No DTD source validators found", !dtdValidatorIDs.isEmpty());
List jspValidatorIDs = getSourceValidatorIDs("testValidatorConfigurations.jsp");
assertTrue("No JSP source validators found", !jspValidatorIDs.isEmpty());
int dtdValidatorCount = dtdValidatorIDs.size();
dtdValidatorIDs.removeAll(jspValidatorIDs);
assertEquals("validators found running on both CSS and DTD", dtdValidatorCount, dtdValidatorIDs.size());
}
}
}