/*******************************************************************************
* Copyright (c) 2012 VMWare, Inc.
* 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:
* VMWare, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.test.gsp;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.groovy.tests.search.AbstractInferencingTest;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.grails.ide.eclipse.editor.gsp.translation.GSPTranslationAdapter;
import org.grails.ide.eclipse.editor.gsp.translation.GSPTranslationAdapterFactory;
import org.grails.ide.eclipse.test.MockGrailsTestProjectUtils;
/**
* Tests to ensure that GSP translation to Groovy works as
* expected
* @author Andrew Eisenberg
* @created Dec 24, 2009
*/
public class GSPTranslationTests extends AbstractInferencingTest {
public static Test suite() {
return buildTestSuite(GSPTranslationTests.class);
}
public GSPTranslationTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
MockGrailsTestProjectUtils.addGrailsNature(project);
}
public void testBasicTranslation1() throws Exception {
checkUserCode(translateText("${text}"), "text");
}
public void testBasicTranslation2() throws Exception {
checkUserCode(translateText("text"), "");
}
public void testBasicTranslation3() throws Exception {
checkUserCode(translateText("${def x = 9\nx++}"), "def x = 9\nx++");
}
public void testTagTranslation1() throws Exception {
checkUserCode(translateText("<g:each>${text}</g:each>"), "\nif(true) { // <g:each>\ntext\n} // </g:each>\n");
}
public void testTagTranslation2() throws Exception {
checkUserCode(translateText("<g:each></g:each>"), "\nif(true) { // <g:each>\n} // </g:each>\n");
}
public void testTagTranslation3() throws Exception {
checkUserCode(translateText("<g:each/>"), "\nif(true) { // <g:each/>\n} // <g:each/>\n");
}
public void testImport1() throws Exception {
String translated = translateText("<%@page import=\"javax.swing.text.html.HTML\"%>\n${new HTML()}");
checkUserCode(translated, "new HTML()\n");
checkImportCode(translated, "import javax.swing.text.html.HTML;");
}
public void testSet() throws Exception {
checkUserCode(translateText("<g:set var=\"entityName\" value=\"${message(code: 'person.label', default: 'Person')}\" />"),
"\n" +
"if(true) { // <g:set/>\n" +
"} // <g:set/>\n" +
"\n" +
"def entityName\n" +
"message(code: 'person.label', default: 'Person')\n"
);
}
public void testSet2() throws Exception {
checkUserCode(translateText("<g:set var=\"entityName\" value=\"${message(code: 'person.label', default: 'Person')}\">text</g:set>"),
"\n" +
"if(true) { // <g:set>\n" +
"\n" +
"def entityName\n" +
"message(code: 'person.label', default: 'Person')\n" +
"} // </g:set>\n"
);
}
public void testDef1() throws Exception {
checkUserCode(translateText("<g:def var=\"entityName\" value=\"${message(code: 'person.label', default: 'Person')}\" />"), "\ndef entityName\n");
}
public void testDef2() throws Exception {
checkUserCode(translateText("<g:def var=\"entityName\" value=\"${message(code: 'person.label', default: 'Person')}\" ></g:def>"), "\ndef entityName\n");
}
public void testEach1() throws Exception {
// this one is a little strange since the g:each tag has no close. The declaration is placed outside of the if statement.
// maybe this is wrong. The variable definition will be available after each tag is closed.
checkUserCode(translateText("<g:each var=\"entityName\" in=\"[1, 2]\" />"), "\n" +
"if(true) { // <g:each/>\n" +
"} // <g:each/>\n" +
"\n" +
"def entityName\n");
}
public void testEach2() throws Exception {
checkUserCode(translateText("<g:each var=\"entityName\" in=\"${[1, 2]}\" ></g:each>"), "\nif(true) { // <g:each>\n\ndef entityName\n[1, 2]\n} // </g:each>\n");
}
public void testEach3() throws Exception {
checkUserCode(translateText("<g:each in=\"${[1, 2]}\" var=\"entityName\" ></g:each>"), "\nif(true) { // <g:each>\n\ndef entityName\n[1, 2]\n} // </g:each>\n");
}
public void testIf() throws Exception {
String translated = translateText("<g:if test=\"${flash.message}\"><div class=\"message\">${flash.message}</div></g:if>");
// slight difference on 35 vs 36 +
String expected35 = "\nwhile(true) { // <g:if>\nflash.message\nflash.message\n} // </g:if>\n";
String expected36 = "\nif(true) { // <g:if>\nflash.message\nflash.message\n} // </g:if>\n";
checkUserCode(translated, expected35, expected36);
}
// Hmmm...how do I check for compile problems?
public void testProblemTranslation1() throws Exception {
// expectingProblemsFor(unit.getResource().getFullPath(),
// "Problem : ...");
checkUserCode(translateText("${new NoExist()}"), "new NoExist()");
}
public void testNestedClosure() throws Exception {
checkUserCode(translateText("${grailsApplication.controllerClasses. sort{ it.fullName }}"), "grailsApplication.controllerClasses. sort{ it.fullName }\n");
}
public void testNestedClosure2() throws Exception {
checkUserCode(translateText(
"<img src=\"${ while(true) {}\n" +
" fdsafsd}\" /> "),
" while(true) {}\n" +
" fdsafsd");
}
public void testSTS1489() throws Exception {
checkUserCode(translateText(
"<img src=\"${ }\" />"), " ");
}
/**
* Like 'checkUserCode(String, String), but accepts multiple alternate 'expectedUserCodes'.
* Either one of the alternates are considered acceptable.
*/
private void checkUserCode(String actualJavaContents, String... expectedUserCode) {
for (int i = 0; i < expectedUserCode.length; i++) {
try {
checkUserCode(actualJavaContents, expectedUserCode[i]);
return; //no need to check others, we have an acceptable match
} catch (AssertionFailedError e) {
if (i+1<expectedUserCode.length) {
//try next alternative
} else {
throw e;
}
}
}
}
/**
* @param unit
* @param expectedUserCode
*/
private void checkUserCode(String actualJavaContents, String expectedUserCode) {
System.out.println(actualJavaContents);
int userCodeStart = actualJavaContents.indexOf("try {\n") + "try {\n".length();
int userCodeEnd = actualJavaContents.lastIndexOf(" } catch (java.lang.Exception e) {} ");
String actualUserCode = actualJavaContents.substring(userCodeStart, userCodeEnd);
assertEquals("Expecting:\n======\n" + expectedUserCode + "\n======\nbut found:\n======\n" + actualUserCode + "\n======\n", userCodeStart, actualJavaContents.indexOf(expectedUserCode, userCodeStart));
}
private void checkImportCode(String javaContents, String importCode) {
int importCodeStart = javaContents.indexOf("import javax.servlet.jsp.*;\n\n") + "import javax.servlet.jsp.*;\n\n".length();
int importCodeEnd = javaContents.lastIndexOf("\npublic class ");
assertEquals("Expecting:\n======\n" + importCode + "\n======\nbut found:\n======\n" + javaContents.substring(importCodeStart, importCodeEnd) + "\n======\n", importCodeStart, javaContents.indexOf(importCode, importCodeStart));
}
private String translateText(String content) throws Exception {
IFile file = project.getFile(new Path("file.gsp"));
if (file.exists()) {
file.delete(true, null);
}
InputStream is = new ByteArrayInputStream(content.getBytes("UTF-8"));
file.create(is, true, null);
IStructuredModel model = StructuredModelManager.getModelManager().getModelForRead(file);
try {
IDOMModel jspModel = (IDOMModel) model;
String jspSource = model.getStructuredDocument().get();
assertTrue("line delimiters have been converted to Windows [CRLF]", jspSource.indexOf("\r\n") < 0);
assertTrue("line delimiters have been converted to Mac [CR]", jspSource.indexOf("\r") < 0);
if (model.getFactoryRegistry().getFactoryFor(IJSPTranslation.class) == null) {
GSPTranslationAdapterFactory factory = new GSPTranslationAdapterFactory();
model.getFactoryRegistry().addFactory(factory);
}
IDOMDocument xmlDoc = jspModel.getDocument();
GSPTranslationAdapter translationAdapter = (GSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
JSPTranslation translation = translationAdapter.getJSPTranslation();
ICompilationUnit unit = translation.getCompilationUnit();
expectingNoProblemsFor(unit.getResource().getFullPath());
return String.valueOf(((CompilationUnit) unit).getContents());
} finally {
model.releaseFromRead();
}
}
}