/*
* Copyright (c) 2007 Henri Sivonen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package nu.validator.htmlparser.test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import nu.validator.htmlparser.common.XmlViolationPolicy;
import nu.validator.htmlparser.impl.ErrorReportingTokenizer;
import nu.validator.htmlparser.impl.Tokenizer;
import nu.validator.htmlparser.io.Driver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import antlr.RecognitionException;
import antlr.TokenStreamException;
import com.sdicons.json.model.JSONArray;
import com.sdicons.json.model.JSONObject;
import com.sdicons.json.model.JSONString;
import com.sdicons.json.model.JSONValue;
import com.sdicons.json.parser.JSONParser;
public class TokenizerTester {
private static JSONString PLAINTEXT = new JSONString("PLAINTEXT state");
private static JSONString PCDATA = new JSONString("DATA state");
private static JSONString RCDATA = new JSONString("RCDATA state");
private static JSONString RAWTEXT = new JSONString("RAWTEXT state");
private static boolean jsonDeepEquals(JSONValue one, JSONValue other) {
if (one.isSimple()) {
return one.equals(other);
} else if (one.isArray()) {
if (other.isArray()) {
JSONArray oneArr = (JSONArray) one;
JSONArray otherArr = (JSONArray) other;
return oneArr.getValue().equals(otherArr.getValue());
} else {
return false;
}
} else if (one.isObject()) {
if (other.isObject()) {
JSONObject oneObject = (JSONObject) one;
JSONObject otherObject = (JSONObject) other;
return oneObject.getValue().equals(otherObject.getValue());
} else {
return false;
}
} else {
throw new RuntimeException("Should never happen.");
}
}
private JSONArray tests;
private final JSONArrayTokenHandler tokenHandler;
private final Driver driver;
private final Writer writer;
private TokenizerTester(InputStream stream) throws TokenStreamException,
RecognitionException, UnsupportedEncodingException {
tokenHandler = new JSONArrayTokenHandler();
driver = new Driver(new ErrorReportingTokenizer(tokenHandler));
driver.setCommentPolicy(XmlViolationPolicy.ALLOW);
driver.setContentNonXmlCharPolicy(XmlViolationPolicy.ALLOW);
driver.setContentSpacePolicy(XmlViolationPolicy.ALLOW);
driver.setNamePolicy(XmlViolationPolicy.ALLOW);
driver.setXmlnsPolicy(XmlViolationPolicy.ALLOW);
driver.setErrorHandler(tokenHandler);
writer = new OutputStreamWriter(System.out, "UTF-8");
JSONParser jsonParser = new JSONParser(new InputStreamReader(stream,
"UTF-8"));
JSONObject obj = (JSONObject) jsonParser.nextValue();
tests = (JSONArray) obj.get("tests");
if (tests == null) {
tests = (JSONArray) obj.get("xmlViolationTests");
driver.setCommentPolicy(XmlViolationPolicy.ALTER_INFOSET);
driver.setContentNonXmlCharPolicy(XmlViolationPolicy.ALTER_INFOSET);
driver.setNamePolicy(XmlViolationPolicy.ALTER_INFOSET);
driver.setXmlnsPolicy(XmlViolationPolicy.ALTER_INFOSET);
}
}
private void runTests() throws SAXException, IOException {
for (JSONValue val : tests.getValue()) {
runTest((JSONObject) val);
}
writer.flush();
}
private void runTest(JSONObject test) throws SAXException, IOException {
String inputString = ((JSONString) test.get("input")).getValue();
JSONArray expectedTokens = (JSONArray) test.get("output");
String description = ((JSONString) test.get("description")).getValue();
JSONString lastStartTagJSON = ((JSONString) test.get("lastStartTag"));
String lastStartTag = lastStartTagJSON == null ? null
: lastStartTagJSON.getValue();
JSONArray contentModelFlags = (JSONArray) test.get("initialStates");
if (contentModelFlags == null) {
runTestInner(inputString, expectedTokens, description,
Tokenizer.DATA, null);
} else {
for (JSONValue value : contentModelFlags.getValue()) {
if (PCDATA.equals(value)) {
runTestInner(inputString, expectedTokens, description,
Tokenizer.DATA, lastStartTag);
} else if (RAWTEXT.equals(value)) {
runTestInner(inputString, expectedTokens, description,
Tokenizer.RAWTEXT, lastStartTag);
} else if (RCDATA.equals(value)) {
runTestInner(inputString, expectedTokens, description,
Tokenizer.RCDATA, lastStartTag);
} else if (PLAINTEXT.equals(value)) {
runTestInner(inputString, expectedTokens, description,
Tokenizer.PLAINTEXT, lastStartTag);
} else {
throw new RuntimeException("Broken test data.");
}
}
}
}
/**
* @param contentModelElement
* @param contentModelFlag
* @param test
* @throws SAXException
* @throws IOException
*/
private void runTestInner(String inputString, JSONArray expectedTokens,
String description, int contentModelFlag,
String contentModelElement) throws SAXException, IOException {
tokenHandler.setContentModelFlag(contentModelFlag, contentModelElement);
InputSource is = new InputSource(new StringReader(inputString));
try {
driver.tokenize(is);
JSONArray actualTokens = tokenHandler.getArray();
if (jsonDeepEquals(actualTokens, expectedTokens)) {
writer.write("Success\n");
} else {
writer.write("Failure\n");
writer.write(description);
writer.write("\nInput:\n");
writer.write(inputString);
writer.write("\nExpected tokens:\n");
writer.write(expectedTokens.render(false));
writer.write("\nActual tokens:\n");
writer.write(actualTokens.render(false));
writer.write("\n");
}
} catch (Throwable t) {
writer.write("Failure\n");
writer.write(description);
writer.write("\nInput:\n");
writer.write(inputString);
writer.write("\n");
t.printStackTrace(new PrintWriter(writer, false));
}
}
/**
* @param args
* @throws RecognitionException
* @throws TokenStreamException
* @throws IOException
* @throws SAXException
*/
public static void main(String[] args) throws TokenStreamException,
RecognitionException, SAXException, IOException {
for (int i = 0; i < args.length; i++) {
TokenizerTester tester = new TokenizerTester(new FileInputStream(
args[i]));
tester.runTests();
}
}
}