001 /* 002 * Copyright (c) 2007 Henri Sivonen 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining a 005 * copy of this software and associated documentation files (the "Software"), 006 * to deal in the Software without restriction, including without limitation 007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 008 * and/or sell copies of the Software, and to permit persons to whom the 009 * Software is furnished to do so, subject to the following conditions: 010 * 011 * The above copyright notice and this permission notice shall be included in 012 * all copies or substantial portions of the Software. 013 * 014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 020 * DEALINGS IN THE SOFTWARE. 021 */ 022 023 package nu.validator.htmlparser.test; 024 025 import java.io.BufferedInputStream; 026 import java.io.BufferedReader; 027 import java.io.FileInputStream; 028 import java.io.IOException; 029 import java.io.InputStream; 030 import java.io.InputStreamReader; 031 import java.io.StringWriter; 032 import java.util.LinkedList; 033 034 import nu.validator.htmlparser.common.XmlViolationPolicy; 035 import nu.validator.htmlparser.sax.HtmlParser; 036 037 import org.xml.sax.InputSource; 038 import org.xml.sax.SAXException; 039 import org.xml.sax.SAXParseException; 040 041 public class TreeTester { 042 043 private final BufferedInputStream aggregateStream; 044 045 private boolean streaming = false; 046 047 /** 048 * @param aggregateStream 049 */ 050 public TreeTester(InputStream aggregateStream) { 051 this.aggregateStream = new BufferedInputStream(aggregateStream); 052 } 053 054 private void runTests() throws Throwable { 055 if (aggregateStream.read() != '#') { 056 System.err.println("No hash at start!"); 057 return; 058 } 059 while (runTest()) { 060 // spin 061 } 062 } 063 064 private boolean runTest() throws Throwable { 065 UntilHashInputStream stream = null; 066 try { 067 String context = null; 068 aggregateStream.mark(4096); 069 if (skipLabel()) { // #data 070 return false; 071 } 072 stream = new UntilHashInputStream(aggregateStream); 073 while (stream.read() != -1) { 074 // spin 075 } 076 if (skipLabel()) { // #errors 077 System.err.println("Premature end of test data."); 078 return false; 079 } 080 stream = new UntilHashInputStream(aggregateStream); 081 while (stream.read() != -1) { 082 // spin 083 } 084 085 StringBuilder sb = new StringBuilder(); 086 int c; 087 while ((c = aggregateStream.read()) != '\n') { 088 sb.append((char) c); 089 } 090 String label = sb.toString(); 091 if ("document-fragment".equals(label)) { 092 sb.setLength(0); 093 while ((c = aggregateStream.read()) != '\n') { 094 sb.append((char) c); 095 } 096 context = sb.toString(); 097 } 098 aggregateStream.reset(); 099 if (skipLabel()) { // #data 100 System.err.println("Premature end of test data."); 101 return false; 102 } 103 stream = new UntilHashInputStream(aggregateStream); 104 InputSource is = new InputSource(stream); 105 is.setEncoding("UTF-8"); 106 StringWriter sw = new StringWriter(); 107 ListErrorHandler leh = new ListErrorHandler(); 108 TreeDumpContentHandler treeDumpContentHandler = new TreeDumpContentHandler( 109 sw); 110 HtmlParser htmlParser = new HtmlParser(XmlViolationPolicy.ALLOW); 111 if (streaming) { 112 htmlParser.setStreamabilityViolationPolicy(XmlViolationPolicy.FATAL); 113 } 114 htmlParser.setContentHandler(treeDumpContentHandler); 115 htmlParser.setLexicalHandler(treeDumpContentHandler); 116 htmlParser.setErrorHandler(leh); 117 htmlParser.setScriptingEnabled(true); 118 try { 119 if (context == null) { 120 htmlParser.parse(is); 121 } else { 122 htmlParser.parseFragment(is, context); 123 treeDumpContentHandler.endDocument(); 124 } 125 } catch (SAXParseException e) { 126 // ignore 127 } 128 stream.close(); 129 130 if (skipLabel()) { // #errors 131 System.err.println("Premature end of test data."); 132 return false; 133 } 134 LinkedList<String> expectedErrors = new LinkedList<String>(); 135 BufferedReader br = new BufferedReader(new InputStreamReader( 136 new UntilHashInputStream(aggregateStream), "UTF-8")); 137 String line = null; 138 while ((line = br.readLine()) != null) { 139 expectedErrors.add(line); 140 } 141 142 if (context != null) { 143 if (skipLabel()) { // #document-fragment 144 System.err.println("Premature end of test data."); 145 return false; 146 } 147 UntilHashInputStream stream2 = new UntilHashInputStream(aggregateStream); 148 while (stream2.read() != -1) { 149 // spin 150 } 151 } 152 153 154 if (skipLabel()) { // #document 155 System.err.println("Premature end of test data."); 156 return false; 157 } 158 159 StringBuilder expectedBuilder = new StringBuilder(); 160 br = new BufferedReader(new InputStreamReader( 161 new UntilHashInputStream(aggregateStream), "UTF-8")); 162 while ((line = br.readLine()) != null) { 163 expectedBuilder.append(line); 164 expectedBuilder.append('\n'); 165 } 166 String expected = expectedBuilder.toString(); 167 String actual = sw.toString(); 168 169 LinkedList<String> actualErrors = leh.getErrors(); 170 171 if (expected.equals(actual) || (streaming && leh.isFatal()) /* 172 * && expectedErrors.size() == 173 * actualErrors.size() 174 */) { 175 System.err.println("Success."); 176 // System.err.println(stream); 177 } else { 178 System.err.print("Failure.\nData:\n" + stream + "\nExpected:\n" 179 + expected + "Got: \n" + actual); 180 System.err.println("Expected errors:"); 181 for (String err : expectedErrors) { 182 System.err.println(err); 183 } 184 System.err.println("Actual errors:"); 185 for (String err : actualErrors) { 186 System.err.println(err); 187 } 188 } 189 } catch (Throwable t) { 190 System.err.println("Failure.\nData:\n" + stream); 191 throw t; 192 } 193 return true; 194 } 195 196 private boolean skipLabel() throws IOException { 197 int b = aggregateStream.read(); 198 if (b == -1) { 199 return true; 200 } 201 for (;;) { 202 b = aggregateStream.read(); 203 if (b == -1) { 204 return true; 205 } else if (b == 0x0A) { 206 return false; 207 } 208 } 209 } 210 211 /** 212 * @param args 213 * @throws Throwable 214 */ 215 public static void main(String[] args) throws Throwable { 216 for (int i = 0; i < args.length; i++) { 217 TreeTester tester = new TreeTester(new FileInputStream(args[i])); 218 tester.runTests(); 219 } 220 } 221 222 }