/******************************************************************************* * Copyright (c) 2004, 2008 John Krasnay and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Krasnay - initial API and implementation *******************************************************************************/ package test.net.sf.vex.layout; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Stack; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import net.sf.vex.css.StyleSheet; import net.sf.vex.css.StyleSheetReader; import net.sf.vex.dom.Document; import net.sf.vex.dom.DocumentReader; import net.sf.vex.dom.IWhitespacePolicy; import net.sf.vex.dom.IWhitespacePolicyFactory; import net.sf.vex.layout.Box; import net.sf.vex.layout.LayoutContext; import net.sf.vex.layout.RootBox; import net.sf.vex.layout.TextBox; import net.sf.vex.widget.CssWhitespacePolicy; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; /** * Runs several suites of layout tests. Each suite is defined in an XML file. * The XML files to run are registered in the suite() method. */ public class LayoutTest extends TestCase { public String id; public String doc; public int layoutWidth = 100; public BoxSpec result; public String css; public static Test suite() throws ParserConfigurationException, FactoryConfigurationError, IOException, SAXException { TestSuite suite = new TestSuite(LayoutTest.class.getName()); suite.addTest(loadSuite("block-inline.xml")); suite.addTest(loadSuite("before-after.xml")); suite.addTest(loadSuite("linebreaks.xml")); suite.addTest(loadSuite("tables.xml")); return suite; } public static Test loadSuite(String filename) throws ParserConfigurationException, FactoryConfigurationError, IOException, SAXException { XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); TestCaseBuilder builder = new TestCaseBuilder(); xmlReader.setContentHandler(builder); //xmlReader.setEntityResolver(builder); URL url = LayoutTest.class.getResource(filename); xmlReader.parse(new InputSource(url.toString())); TestSuite suite = new TestSuite(filename); for (Iterator it = builder.testCases.iterator(); it.hasNext();) { LayoutTest test = (LayoutTest) it.next(); suite.addTest(test); } return suite; } public LayoutTest() { super("testLayout"); } public String getName() { return this.id; } public void testLayout() throws Exception { System.out.println(); System.out.println("-----------------------------------------------------------------------"); System.out.println("Test: " + this.id); System.out.println("-----------------------------------------------------------------------"); URL url = LayoutTest.class.getResource(this.css); StyleSheetReader reader = new StyleSheetReader(); final StyleSheet ss = reader.read(url); FakeGraphics g = new FakeGraphics(); LayoutContext context = new LayoutContext(); context.setBoxFactory(new TestBoxFactory()); context.setGraphics(g); context.setStyleSheet(ss); DocumentReader docReader = new DocumentReader(); docReader.setWhitespacePolicyFactory(new IWhitespacePolicyFactory() { public IWhitespacePolicy getPolicy(String publicId) { return new CssWhitespacePolicy(ss); } }); Document doc = docReader.read(this.doc); context.setDocument(doc); RootBox rootBox = new RootBox(context, doc.getRootElement(), this.layoutWidth); rootBox.layout(context, 0, Integer.MAX_VALUE); assertBox(this.result, rootBox, ""); } private static void assertBox(BoxSpec boxSpec, Box box, String indent) { System.out.println(indent + boxSpec.className); if (boxSpec.className != null) { String actualClassName = box.getClass().getName(); if (boxSpec.className.lastIndexOf('.') == -1) { // no dot in box spec classname, so strip the prefix from the actual classname int lastDot = actualClassName.lastIndexOf('.'); actualClassName = actualClassName.substring(lastDot + 1); } assertEquals(boxSpec.className, actualClassName); } if (boxSpec.element != null) { assertNotNull(box.getElement()); assertEquals(boxSpec.element, box.getElement().getName()); } if (boxSpec.text != null && box instanceof TextBox) { assertEquals(boxSpec.text, ((TextBox) box).getText()); } if (boxSpec.children.size() > 0 && box.getChildren() == null) { fail("Expected " + boxSpec.children.size() + " children, but " + boxSpec.className + "'s children is null"); } if (boxSpec.children.size() != box.getChildren().length) { System.out.println("Wrong number of child boxes"); System.out.println(" Expected:"); for (Iterator it = boxSpec.children.iterator(); it.hasNext();) { BoxSpec childSpec = (BoxSpec) it.next(); System.out.print(" " + childSpec.className); if (childSpec.text != null) { System.out.print(" '" + childSpec.text + "'"); } System.out.println(); } System.out.println(" Actual:"); for (int i = 0; i < box.getChildren().length; i++) { Box childBox = box.getChildren()[i]; System.out.println(" " + childBox.getClass() + ": " + childBox); } fail("Wrong number of child boxes."); } for (int i = 0; i < boxSpec.children.size(); i++) { assertBox((BoxSpec) boxSpec.children.get(i), box.getChildren() [i], indent + " "); } } private static class TestCaseBuilder extends DefaultHandler { private List testCases; private String css; private LayoutTest testCase; private BoxSpec boxSpec; private Stack boxSpecs; private boolean inDoc; public void characters(char[] ch, int start, int length) throws SAXException { String s = new String(ch, start, length).trim(); if (s.length() > 0) { if (inDoc) { this.testCase.doc = new String(ch, start, length); } else { throw new IllegalStateException(); } } } public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("box")) { if (this.boxSpecs.isEmpty()) { this.boxSpec = null; } else { this.boxSpec = (BoxSpec) this.boxSpecs.pop(); } } else if (qName.equals("doc")) { this.inDoc = false; } } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("testcases")) { this.testCases = new ArrayList(); this.css = attributes.getValue("css"); if (this.css == null) { this.css = "test.css"; } this.testCase = null; this.boxSpecs = new Stack(); } else if (qName.equals("test")) { this.testCase = new LayoutTest(); this.testCase.id = attributes.getValue("id"); this.testCase.css = this.css; String layoutWidth = attributes.getValue("layoutWidth"); if (layoutWidth != null) { this.testCase.layoutWidth = Integer.parseInt(layoutWidth); } testCases.add(this.testCase); } else if (qName.equals("doc")) { this.inDoc = true; } else if (qName.equals("result")) { } else if (qName.equals("box")) { BoxSpec parent = this.boxSpec; this.boxSpec = new BoxSpec(); this.boxSpec.className = attributes.getValue("class"); this.boxSpec.element = attributes.getValue("element"); this.boxSpec.text = attributes.getValue("text"); if (parent == null) { this.testCase.result = this.boxSpec; } else { this.boxSpecs.push(parent); parent.children.add(this.boxSpec); } } else { throw new SAXException("Unrecognized element: " + qName); } } } private static class BoxSpec { public String className; public String element; public List children = new ArrayList(); public String text; } }