/*
* 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.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.LinkedList;
import nu.validator.htmlparser.common.XmlViolationPolicy;
import nu.validator.htmlparser.sax.HtmlParser;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
public class TreeTester {
private final BufferedInputStream aggregateStream;
private boolean streaming = false;
/**
* @param aggregateStream
*/
public TreeTester(InputStream aggregateStream) {
this.aggregateStream = new BufferedInputStream(aggregateStream);
}
private void runTests() throws Throwable {
if (aggregateStream.read() != '#') {
System.err.println("No hash at start!");
return;
}
while (runTest()) {
// spin
}
}
private boolean runTest() throws Throwable {
UntilHashInputStream stream = null;
try {
String context = null;
boolean scriptingEnabled = true;
boolean hadScriptingDirective = false;
aggregateStream.mark(12288);
if (skipLabel()) { // #data
return false;
}
stream = new UntilHashInputStream(aggregateStream);
while (stream.read() != -1) {
// spin
}
if (skipLabel()) { // #errors
System.err.println("Premature end of test data.");
return false;
}
stream = new UntilHashInputStream(aggregateStream);
while (stream.read() != -1) {
// spin
}
StringBuilder sb = new StringBuilder();
int c;
while ((c = aggregateStream.read()) != '\n') {
sb.append((char) c);
}
String label = sb.toString();
if ("document-fragment".equals(label)) {
sb.setLength(0);
while ((c = aggregateStream.read()) != '\n') {
sb.append((char) c);
}
context = sb.toString();
// Now potentially gather #script-on/off
sb.setLength(0);
while ((c = aggregateStream.read()) != '\n') {
sb.append((char) c);
}
label = sb.toString();
}
if ("script-on".equals(label)) {
hadScriptingDirective = true;
} else if ("script-off".equals(label)) {
hadScriptingDirective = true;
scriptingEnabled = false;
}
aggregateStream.reset();
if (skipLabel()) { // #data
System.err.println("Premature end of test data.");
return false;
}
stream = new UntilHashInputStream(aggregateStream);
InputSource is = new InputSource(stream);
is.setEncoding("UTF-8");
StringWriter sw = new StringWriter();
ListErrorHandler leh = new ListErrorHandler();
TreeDumpContentHandler treeDumpContentHandler = new TreeDumpContentHandler(
sw);
HtmlParser htmlParser = new HtmlParser(XmlViolationPolicy.ALLOW);
if (streaming) {
htmlParser.setStreamabilityViolationPolicy(XmlViolationPolicy.FATAL);
}
htmlParser.setContentHandler(treeDumpContentHandler);
htmlParser.setLexicalHandler(treeDumpContentHandler);
htmlParser.setErrorHandler(leh);
htmlParser.setScriptingEnabled(scriptingEnabled);
try {
if (context == null) {
htmlParser.parse(is);
} else {
String ns = "http://www.w3.org/1999/xhtml";
if (context.startsWith("svg ")) {
ns = "http://www.w3.org/2000/svg";
context = context.substring(4);
} else if (context.startsWith("math ")) {
ns = "http://www.w3.org/1998/Math/MathML";
context = context.substring(5);
}
htmlParser.parseFragment(is, context, ns);
treeDumpContentHandler.endDocument();
}
} catch (SAXParseException e) {
// ignore
}
stream.close();
if (skipLabel()) { // #errors
System.err.println("Premature end of test data.");
return false;
}
LinkedList<String> expectedErrors = new LinkedList<String>();
BufferedReader br = new BufferedReader(new InputStreamReader(
new UntilHashInputStream(aggregateStream), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
expectedErrors.add(line);
}
if (context != null) {
if (skipLabel()) { // #document-fragment
System.err.println("Premature end of test data.");
return false;
}
UntilHashInputStream stream2 = new UntilHashInputStream(aggregateStream);
while (stream2.read() != -1) {
// spin
}
}
if (hadScriptingDirective && skipLabel()) { // #script-on/off
System.err.println("Premature end of test data.");
return false;
}
if (skipLabel()) { // #document
System.err.println("Premature end of test data.");
return false;
}
StringBuilder expectedBuilder = new StringBuilder();
br = new BufferedReader(new InputStreamReader(
new UntilHashInputStream(aggregateStream), "UTF-8"));
int ch;
while ((ch = br.read()) != -1) {
expectedBuilder.append((char)ch);
}
String expected = expectedBuilder.toString();
String actual = sw.toString();
LinkedList<String> actualErrors = leh.getErrors();
if (expected.equals(actual) || (streaming && leh.isFatal()) /*
* && expectedErrors.size() ==
* actualErrors.size()
*/) {
System.err.println("Success.");
// System.err.println(stream);
} else {
System.err.print("Failure.\nData:\n" + stream + "\nExpected:\n"
+ expected + "Got: \n" + actual);
System.err.println("Expected errors:");
for (String err : expectedErrors) {
System.err.println(err);
}
System.err.println("Actual errors:");
for (String err : actualErrors) {
System.err.println(err);
}
}
} catch (Throwable t) {
System.err.println("Failure.\nData:\n" + stream);
throw t;
}
return true;
}
private boolean skipLabel() throws IOException {
int b = aggregateStream.read();
if (b == -1) {
return true;
}
for (;;) {
b = aggregateStream.read();
if (b == -1) {
return true;
} else if (b == 0x0A) {
return false;
}
}
}
/**
* @param args
* @throws Throwable
*/
public static void main(String[] args) throws Throwable {
for (int i = 0; i < args.length; i++) {
TreeTester tester = new TreeTester(new FileInputStream(args[i]));
tester.runTests();
}
}
}