You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LayoutEngineTester.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.layoutengine;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.util.Collection;
  22. import java.util.List;
  23. import javax.xml.parsers.ParserConfigurationException;
  24. import javax.xml.transform.Source;
  25. import javax.xml.transform.Transformer;
  26. import javax.xml.transform.TransformerException;
  27. import javax.xml.transform.TransformerFactory;
  28. import javax.xml.transform.dom.DOMResult;
  29. import javax.xml.transform.dom.DOMSource;
  30. import javax.xml.transform.sax.SAXResult;
  31. import javax.xml.transform.sax.TransformerHandler;
  32. import org.junit.BeforeClass;
  33. import org.junit.Test;
  34. import org.junit.runner.RunWith;
  35. import org.junit.runners.Parameterized;
  36. import org.junit.runners.Parameterized.Parameters;
  37. import org.w3c.dom.Document;
  38. import org.w3c.dom.Element;
  39. import org.w3c.dom.NodeList;
  40. import org.xml.sax.ContentHandler;
  41. import org.xml.sax.SAXException;
  42. import org.apache.fop.DebugHelper;
  43. import org.apache.fop.apps.FOUserAgent;
  44. import org.apache.fop.apps.Fop;
  45. import org.apache.fop.apps.FopFactory;
  46. import org.apache.fop.apps.FormattingResults;
  47. import org.apache.fop.area.AreaTreeModel;
  48. import org.apache.fop.area.AreaTreeParser;
  49. import org.apache.fop.area.RenderPagesModel;
  50. import org.apache.fop.events.model.EventSeverity;
  51. import org.apache.fop.fonts.FontInfo;
  52. import org.apache.fop.intermediate.IFTester;
  53. import org.apache.fop.intermediate.TestAssistant;
  54. import org.apache.fop.layoutmgr.ElementListObserver;
  55. import org.apache.fop.render.intermediate.IFContext;
  56. import org.apache.fop.render.intermediate.IFRenderer;
  57. import org.apache.fop.render.intermediate.IFSerializer;
  58. import org.apache.fop.render.xml.XMLRenderer;
  59. import org.apache.fop.util.ConsoleEventListenerForTests;
  60. import org.apache.fop.util.DelegatingContentHandler;
  61. /**
  62. * Class for testing the FOP's layout engine using testcases specified in XML
  63. * files.
  64. */
  65. @RunWith(Parameterized.class)
  66. public class LayoutEngineTester {
  67. private static File areaTreeBackupDir;
  68. @BeforeClass
  69. public static void makeDirAndRegisterDebugHelper() throws IOException {
  70. DebugHelper.registerStandardElementListObservers();
  71. areaTreeBackupDir = new File("build/test-results/layoutengine");
  72. if (!areaTreeBackupDir.mkdirs() && !areaTreeBackupDir.exists()) {
  73. throw new IOException("Failed to create the layout engine directory at "
  74. + "build/test-results/layoutengine");
  75. }
  76. }
  77. /**
  78. * Creates the parameters for this test.
  79. *
  80. * @return the list of file arrays populated with test files
  81. * @throws IOException if an I/O error occurs while reading the test file
  82. */
  83. @Parameters
  84. public static Collection<File[]> getParameters() throws IOException {
  85. return LayoutEngineTestUtils.getLayoutTestFiles();
  86. }
  87. private TestAssistant testAssistant = new TestAssistant();
  88. private LayoutEngineChecksFactory layoutEngineChecksFactory = new LayoutEngineChecksFactory();
  89. private IFTester ifTester;
  90. private File testFile;
  91. private TransformerFactory tfactory = TransformerFactory.newInstance();
  92. /**
  93. * Constructs a new instance.
  94. *
  95. * @param testFile the test file
  96. */
  97. public LayoutEngineTester(File testFile) {
  98. this.ifTester = new IFTester(tfactory, areaTreeBackupDir);
  99. this.testFile = testFile;
  100. }
  101. /**
  102. * Runs a single layout engine test case.
  103. * @throws TransformerException In case of an XSLT/JAXP problem
  104. * @throws IOException In case of an I/O problem
  105. * @throws SAXException In case of a problem during SAX processing
  106. * @throws ParserConfigurationException In case of a problem with the XML parser setup
  107. */
  108. @Test
  109. public void runTest() throws TransformerException, SAXException, IOException,
  110. ParserConfigurationException {
  111. DOMResult domres = new DOMResult();
  112. ElementListCollector elCollector = new ElementListCollector();
  113. ElementListObserver.addObserver(elCollector);
  114. Fop fop;
  115. FopFactory effFactory;
  116. try {
  117. Document testDoc = testAssistant.loadTestCase(testFile);
  118. effFactory = testAssistant.getFopFactory(testDoc);
  119. //Setup Transformer to convert the testcase XML to XSL-FO
  120. Transformer transformer = testAssistant.getTestcase2FOStylesheet().newTransformer();
  121. Source src = new DOMSource(testDoc);
  122. //Setup Transformer to convert the area tree to a DOM
  123. TransformerHandler athandler;
  124. athandler = testAssistant.getTransformerFactory().newTransformerHandler();
  125. athandler.setResult(domres);
  126. //Setup FOP for area tree rendering
  127. FOUserAgent ua = effFactory.newFOUserAgent();
  128. ua.setBaseURL(testFile.getParentFile().toURI().toURL().toString());
  129. ua.getEventBroadcaster().addEventListener(
  130. new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN));
  131. XMLRenderer atrenderer = new XMLRenderer();
  132. atrenderer.setUserAgent(ua);
  133. atrenderer.setContentHandler(athandler);
  134. ua.setRendererOverride(atrenderer);
  135. fop = effFactory.newFop(ua);
  136. SAXResult fores = new SAXResult(fop.getDefaultHandler());
  137. transformer.transform(src, fores);
  138. } finally {
  139. ElementListObserver.removeObserver(elCollector);
  140. }
  141. Document doc = (Document)domres.getNode();
  142. if (areaTreeBackupDir != null) {
  143. testAssistant.saveDOM(doc,
  144. new File(areaTreeBackupDir, testFile.getName() + ".at.xml"));
  145. }
  146. FormattingResults results = fop.getResults();
  147. LayoutResult result = new LayoutResult(doc, elCollector, results);
  148. checkAll(effFactory, testFile, result);
  149. }
  150. /**
  151. * Perform all checks on the area tree and, optionally, on the intermediate format.
  152. * @param fopFactory the FOP factory
  153. * @param testFile Test case XML file
  154. * @param result The layout results
  155. * @throws TransformerException if a problem occurs in XSLT/JAXP
  156. */
  157. protected void checkAll(FopFactory fopFactory, File testFile, LayoutResult result)
  158. throws TransformerException {
  159. Element testRoot = testAssistant.getTestRoot(testFile);
  160. NodeList nodes;
  161. //AT tests only when checks are available
  162. nodes = testRoot.getElementsByTagName("at-checks");
  163. if (nodes.getLength() > 0) {
  164. Element atChecks = (Element)nodes.item(0);
  165. doATChecks(atChecks, result);
  166. }
  167. //IF tests only when checks are available
  168. nodes = testRoot.getElementsByTagName("if-checks");
  169. if (nodes.getLength() > 0) {
  170. Element ifChecks = (Element)nodes.item(0);
  171. Document ifDocument = createIF(fopFactory, testFile, result.getAreaTree());
  172. ifTester.doIFChecks(testFile.getName(), ifChecks, ifDocument);
  173. }
  174. }
  175. private Document createIF(FopFactory fopFactory, File testFile, Document areaTreeXML)
  176. throws TransformerException {
  177. try {
  178. FOUserAgent ua = fopFactory.newFOUserAgent();
  179. ua.setBaseURL(testFile.getParentFile().toURI().toURL().toExternalForm());
  180. ua.getEventBroadcaster().addEventListener(
  181. new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN));
  182. IFRenderer ifRenderer = new IFRenderer();
  183. ifRenderer.setUserAgent(ua);
  184. IFSerializer serializer = new IFSerializer();
  185. serializer.setContext(new IFContext(ua));
  186. DOMResult result = new DOMResult();
  187. serializer.setResult(result);
  188. ifRenderer.setDocumentHandler(serializer);
  189. ua.setRendererOverride(ifRenderer);
  190. FontInfo fontInfo = new FontInfo();
  191. //Construct the AreaTreeModel that will received the individual pages
  192. final AreaTreeModel treeModel = new RenderPagesModel(ua,
  193. null, fontInfo, null);
  194. //Iterate over all intermediate files
  195. AreaTreeParser parser = new AreaTreeParser();
  196. ContentHandler handler = parser.getContentHandler(treeModel, ua);
  197. DelegatingContentHandler proxy = new DelegatingContentHandler() {
  198. public void endDocument() throws SAXException {
  199. super.endDocument();
  200. //Signal the end of the processing.
  201. //The renderer can finalize the target document.
  202. treeModel.endDocument();
  203. }
  204. };
  205. proxy.setDelegateContentHandler(handler);
  206. Transformer transformer = tfactory.newTransformer();
  207. transformer.transform(new DOMSource(areaTreeXML), new SAXResult(proxy));
  208. return (Document)result.getNode();
  209. } catch (Exception e) {
  210. throw new TransformerException(
  211. "Error while generating intermediate format file: " + e.getMessage(), e);
  212. }
  213. }
  214. private void doATChecks(Element checksRoot, LayoutResult result) {
  215. List<LayoutEngineCheck> checks = layoutEngineChecksFactory.createCheckList(checksRoot);
  216. if (checks.size() == 0) {
  217. throw new RuntimeException("No available area tree check");
  218. }
  219. for (LayoutEngineCheck check : checks) {
  220. check.check(result);
  221. }
  222. }
  223. }