/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.xml; import java.io.StringWriter; import junit.framework.TestCase; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; public class PrettyPrinterTest extends TestCase { protected static final String EMPTY_NAMESPACE = ""; protected static final String EMPTY_LOCALNAME = ""; private static final String NL = System.getProperty("line.separator"); public PrettyPrinterTest(String name) { super(name); } public void testMinimalDocument() { try { StringWriter writer = new StringWriter(); PrettyPrinter printer = setUpPrinter(writer); printer.startElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc", new AttributesImpl()); printer.endElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc"); printer.endDocument(); verify(writer, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" + NL + "<doc>" + "</doc>" + NL); } catch (SAXException e) { assertTrue("SAXException: " + e, false); } } public void testDocumentWithAllConstructs() { try { StringWriter writer = new StringWriter(); PrettyPrinter printer = setUpPrinter(writer); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "a", "CDATA", "v"); printer.startElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc", attrs); printer.processingInstruction("pi", "data"); String str = "A bit of character data!"; printer.characters(str.toCharArray(), 0, str.length()); str = " "; printer.ignorableWhitespace(str.toCharArray(), 0, str.length()); printer.endElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc"); printer.endDocument(); verify(writer, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" + NL + "<doc a=\"v\"><?pi data?>" + "A bit of character data!</doc>" + NL); } catch (SAXException e) { assertTrue("SAXException: " + e, false); } } public void testChardataEscaping() { try { StringWriter writer = new StringWriter(); PrettyPrinter printer = setUpPrinter(writer); printer.startElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc", new AttributesImpl()); String str = "A <, and a & and a >."; printer.characters(str.toCharArray(), 0, str.length()); printer.endElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc"); printer.endDocument(); verify(writer, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" + NL + "<doc>A <, and a & and a >.</doc>" + NL); } catch (SAXException e) { assertTrue("SAXException: " + e, false); } } public void testAttributeEscaping() { try { StringWriter writer = new StringWriter(); PrettyPrinter printer = setUpPrinter(writer); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "a", "CDATA", "\"<&"); printer.startElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc", attrs); printer.endElement(EMPTY_NAMESPACE, EMPTY_LOCALNAME, "doc"); printer.endDocument(); verify(writer, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" + NL + "<doc a=\""<&\"></doc>" + NL); } catch (SAXException e) { assertTrue("SAXException: " + e, false); } } // --- Internal methods private PrettyPrinter setUpPrinter(StringWriter writer) throws SAXException { PrettyPrinter pp = new PrettyPrinter(writer, "iso-8859-1"); pp.startDocument(); return pp; } private void verify(StringWriter out, String expected) { String result = out.toString(); int elen = expected.length(); int rlen = result.length(); int ix; for (ix = 0; ix < rlen && ix < elen && result.charAt(ix) == expected.charAt(ix); ix++) ; if (ix < rlen && rlen > elen) fail("Result longer than expected; expected: " + elen + "; " + "result: " + rlen + "; rest: " + getRest(result, expected)); else if (ix < elen && rlen < elen) fail("Result shorter than expected; expected: " + elen + "; " + "result: " + rlen + "; rest: " + getRest(expected, result)); else if (ix < rlen && rlen == elen) fail("Result differs from expected in position " + ix + "; " + "result: " + result.charAt(ix) + " (" + encode(result.charAt(ix)) + "; " + "expected: " + expected.charAt(ix) + " (" + encode(expected.charAt(ix))); } // assumes s1.length() > s2.length() private String getRest(String s1, String s2) { StringBuilder buf = new StringBuilder(); for (int ix = s2.length(); ix < s1.length(); ix++) buf.append(encode(s1.charAt(ix)) + " "); return buf.toString(); } private String encode(char ch) { return ("U+" + encodeHexDigit((ch & 0xF000) >> 12) + encodeHexDigit((ch & 0x0F00) >> 8) + encodeHexDigit((ch & 0x00F0) >> 4) + encodeHexDigit(ch & 0x000F)); } private char encodeHexDigit(int value) { if (value <= 9) return (char) ('0' + value); else return (char) ('A' + (value - 10)); } }