package csep.tests;
import java.io.InputStream;
import java.util.List;
import junit.framework.AssertionFailedError;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.xtext.junit.AbstractXtextTests;
import org.eclipse.xtext.resource.XtextResource;
import csep.CoffeeScriptStandaloneSetup;
import csep.parser.Helper;
import csep.parser.Lexer;
/**
* Enable testing if a code snippet gets parsed as expected.
*
* @author Adam Schmideg <adam@schmideg.net>
*/
public abstract class ParserTestBase extends AbstractXtextTests {
private final static Logger logger = Logger.getLogger(ParserTestBase.class);
@Override
protected void setUp() throws Exception {
super.setUp();
with(new CoffeeScriptStandaloneSetup());
}
/**
* XXX: Always return false, otherwise {@link AbstractXtextTests} will check whitespaces,
* so for example "a = 2" would fail, because it's not equal to its serialized version "a=2".
*/
@Override
protected boolean shouldTestSerializer(XtextResource resource) {
return false;
}
/**
* Parse and check for errors and warnings
* @param errorCount 1 means expect error(s)
* @param warningCount -1 means don't care about warnings
*/
protected void expect(CharSequence input, int errorCount, int warningCount) {
List<String> tokens = null;
//Assert::assertEquals('warnings ' + resource.warnings, 0, resource.warnings.size)
//Assert::assertEquals('errors ' + resource.errors, 0, resource.errors.size)
EObject parseResult = null;
EList<Diagnostic> errors = null;
EList<Diagnostic> warnings = null;
try {
Lexer lexer = new Lexer(input);
tokens = lexer.tokenizeToStrings();
InputStream in = getAsStream("" + input);
URI uri = URI.createURI("mytestmodel." + getCurrentFileExtension());
XtextResource resource = doGetResource(in, uri);
parseResult = getModel(resource);
errors = resource.getErrors();
warnings = resource.getWarnings();
if (errorCount == 0)
assertEquals("Errors: " + errors, 0, errors.size());
else if (errorCount > 0)
assertTrue("No errors", errors.size() > 0);
if (warningCount >= 0) {
assertEquals("Warnings: " + warnings, warningCount, warnings.size());
}
} catch (AssertionFailedError afe) {
if (logger.isDebugEnabled()) {
String debug = "" + this.getClass().getSimpleName() + " input: \n" + input + "\n";
debug += "Tokens: " + tokens + "\n" + Helper.stringify(parseResult);
for (Diagnostic d: errors) {
debug += "\tError: " + d + "\n";
}
for (Diagnostic d: warnings) {
debug += "\tWarning: " + d + "\n";
}
logger.debug(debug);
}
throw new AssertionError(afe);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Input can be parsed without syntax errors
* @param input typically a String or a multiline xtend String
*/
public void ok(CharSequence input) {
expect(input, 0, -1);
}
/**
* Parsing input results in one syntax error
* @param input
*/
public void error(CharSequence input) {
expect(input, 1, -1);
}
/**
* Indicate that a test case should parse, but it gives errors
*/
public void shouldBeOk(CharSequence input) {
String clazz = this.getClass().getSimpleName();
boolean wasOk = false;
try {
ok(input);
wasOk = true;
}
catch (AssertionError afe) {
logger.warn("Expected to successfully parse " + clazz + " '" + input + "', but " + afe.getMessage());
}
if (wasOk) {
fail("Expected an error, but parsed successfully '" + input + "'");
}
}
/**
* It parses and has no warnings
* @param input
*/
public void okNoWarning(CharSequence input) {
expect(input, 0, 0);
}
public void shouldBeOkNoWarning(CharSequence input) {
String clazz = this.getClass().getSimpleName();
boolean wasOk = false;
try {
okNoWarning(input);
wasOk = true;
}
catch (AssertionError afe) {
logger.warn("Expected to parse without warning " + clazz + " '" + input + "', but " + afe.getMessage());
}
if (wasOk) {
fail("Expected a warning, but parsed successfully '" + input + "'");
}
}
}