/**
* InstantJ
*
* Copyright (C) 2002 Nils Meier
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
package instantj.tst;
import instantj.reflect.PropertyException;
import instantj.reflect.ReflectAccess;
import instantj.compile.CompilationFailedException;
import instantj.expression.Expression;
import instantj.expression.EvaluationFailedException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* Runs tests read from configuration descriptors
*/
public class DescriptorTest implements FileFilter {
/**
* MAIN
*/
public static void main(String[] args) {
// Disclaimer
System.out.println("InstantJ - "+ReflectAccess.getInstance().calcClassNameOf(DescriptorTest.class));
// Check the args - we need the directory folder where
// the test-cases reside in
if (args.length!=1) {
System.out.println("Usage: java instantj.tst.RunTests [folder]");
return;
}
// Check if folder exists
File folder = new File(args[0]);
if (!folder.exists()) {
System.out.println("Folder "+folder+" doesn't exist!");
return;
}
// Run the test
new DescriptorTest(folder);
// Done
System.out.println("Done");
// .. we want to make sure that we actually quit
// (could have an awt thread sticking around)
System.exit(0);
}
/**
* Constructor
*/
private DescriptorTest(File folder) {
// Try to get a parser
SAXParser parser;
try {
parser = SAXParserFactory.newInstance().newSAXParser();
} catch (Throwable t) {
System.out.println("Couldn't instantiate SAXParser because of "+t.getClass().getName()+"#"+t.getMessage());
return;
}
// Try to open the tests
File[] files = getTests(folder);
for (int i = 0; i < files.length; i++) {
test(files[i],parser);
}
// Done
}
/**
* Callback whether we accept a given file or not
*/
public boolean accept(File file) {
return file.getAbsolutePath().endsWith(".xml");
}
/**
* Helper that resolves tests from given folder
*/
private File[] getTests(File folder) {
// Info
System.out.println("Looking for *.xml in "+folder);
// Here's the list
return folder.listFiles(this);
}
/**
* Run a single test
*/
private void test(File test, SAXParser parser) {
// we have to handle the case of some IO problem
try {
// open the file
InputStream in = new FileInputStream(test);
// and parse it
Configuration conf = parse(in, parser);
// and execute it
evaluate(test, conf);
// done
in.close();
} catch (SAXException e) {
System.out.println("Parsing test "+test.getName()+" failed because of "+e.getClass().getName()+"#"+e.getMessage());
} catch (IOException e) {
System.out.println("Reading test "+test.getName()+" failed because of "+e.getClass().getName()+"#"+e.getMessage());
}
}
/**
* Evaluates an expression
*/
private void evaluate(File test, Configuration conf) {
System.out.print("Evaluating \""+conf.getTitle()+"\" ("+test+")");
// Try to compile the expression
Expression ex;
try {
ex = new Expression(conf.getExpression(),conf.getProperties());
} catch (CompilationFailedException cfe) {
System.out.println(" failed because of compilation problem: "+cfe.getMessage());
cfe.printErrors(System.out);
return;
}
// Try to evaluate the expression in its context
Object result;
try {
// now we create an instance for the expression and let it grab
// necessary properties from the map we've collected but
// alternatively we could set properties ourselves with :
// ex.getInstance().set("something", somevalue).set("else", anothervalue).evaluate().
result = ex.getInstance(conf.getValues()).evaluate();
} catch (PropertyException mpe) {
System.out.println(" failed : "+mpe.getMessage());
return;
} catch (EvaluationFailedException efe) {
System.out.println(" failed : "+efe.getMessage());
return;
}
// Done
System.out.println(" resulted in ("+result.getClass().getName()+") "+result);
}
/**
* Parses a test
*/
private Configuration parse(InputStream in, SAXParser parser) throws IOException, SAXException {
ExpressionDescriptorHandler handler = new ExpressionDescriptorHandler();
parser.parse(in, handler);
return handler.getConfiguration();
}
/**
* An expression that's configured in the descriptor
*/
static class Configuration {
/** the title */
private String title = null;
/** the expression */
private String expression = null;
/** the property types */
private Map properties = new HashMap();
/** the property values */
private Map values = new HashMap();
/**
* Helper that adds an property
*/
void addProperty(String pName, String pType, String pValue) throws IllegalArgumentException {
// We simply remember the tpye and value as java.lang.String and
// rely on ReflectAccess underlying Expression to later transform
// that into something typed
properties.put(pName, pType);
values.put(pName, pValue);
// We could have used ReflectAccess here to provide something
// that is already typed correctly, too
// Class type = ReflectAccess.getInstance().calcClass(pType);
// Object value = ReflectAccess.getInstance().calcTypedInstance(pValue, type);
// propertyTypes.put (pName, type);
// propertyValues.put(pName, value);
}
/**
* Accessor - the expression
*/
String getExpression() {
return expression.toString();
}
/**
* Accessor - the expression
*/
void setExpression(String pExpression) {
expression = pExpression;
}
/**
* Accessor - the title
*/
String getTitle() {
return title;
}
/**
* Accessor - the title
*/
void setTitle(String pTitle) {
title = pTitle;
}
/**
* Gets the properties.
* @return returns the mapping between property-names and -types
*/
Map getProperties() {
return properties;
}
/**
* Gets the values.
* @return returns the mapping between property-names and -values
*/
Map getValues() {
return values;
}
}
/**
* A SAX 'Default' Handler that knows how to read a test-case
*/
/*package*/ static class ExpressionDescriptorHandler extends DefaultHandler {
/** the result */
private Configuration configuration = new Configuration();
/** the expression we gather */
private StringBuffer expression = new StringBuffer();
/** the elements we know */
private final static String
ELEM_TEST = "test",
ELEM_PROPERTY = "property",
ELEM_EXPRESSION = "expression";
/** the attributes we know */
private final static String
ATTR_TYPE = "type",
ATTR_NAME = "name",
ATTR_VALUE = "value";
/**
* @see DocumentHandler#startElement(String, AttributeList)
*/
public void startElement (String uri, String localName, String elemName, Attributes attributes) throws SAXException {
// we keep the element
expression.append('<');
expression.append(elemName);
expression.append('>');
// A property ?
if (ELEM_PROPERTY.equals(elemName)) {
// .. get its attributes
String name = attributes.getValue(ATTR_NAME );
String type = attributes.getValue(ATTR_TYPE );
String value = attributes.getValue(ATTR_VALUE);
// .. check validity
if ((name==null)||(type==null)||(value==null)) {
throw new SAXException("Element "+ELEM_PROPERTY+" requires attributes "+ATTR_NAME+"&"+ATTR_TYPE+"&"+ATTR_VALUE);
}
// .. and remember
try {
configuration.addProperty(name, type, value);
} catch (IllegalArgumentException e) {
throw new SAXException(e.getMessage()+" for attributes "+ATTR_NAME+"&"+ATTR_TYPE+"&"+ATTR_VALUE);
}
}
// The expression?
if (ELEM_EXPRESSION.equals(elemName)) {
// .. the initial comment ends because that's the code we need
expression.append("*/");
}
// The test?
if (ELEM_TEST.equals(elemName)) {
// .. get the title
configuration.setTitle(attributes.getValue("title"));
}
// Done
}
/**
* Receive notification of the end of an element.
*/
public void endElement (String uri, String localName, String elemName) throws SAXException {
// After the expression is considered to be comment again
if (ELEM_EXPRESSION.equals(elemName)) {
expression.append("/*");
}
// we keep the element
expression.append("</");
expression.append(elemName);
expression.append('>');
}
/**
* Receive notification of character data inside an element.
*/
public void characters (char ch[], int start, int length) throws SAXException {
expression.append(ch, start, length);
}
/**
* Returns the configuration
*/
/*package*/ Configuration getConfiguration() {
return configuration;
}
/**
* Callback for startDocument
*/
public void startDocument () throws SAXException {
// we start out with a comment until we hit ELEM_EXPRESSION
expression.append("/*");
}
/**
* Callback for endDocument
*/
public void endDocument () throws SAXException {
// we end the comment we started in the beginning
expression.append("*/");
// and keep the result
configuration.setExpression(expression.toString());
}
}
}
|