| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.tools; |
| |
| import java.io.File; |
| import java.io.OutputStream; |
| import java.util.Map; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| |
| import org.apache.fop.apps.FopFactory; |
| import org.apache.fop.apps.FOUserAgent; |
| import org.apache.fop.apps.MimeConstants; |
| import org.apache.fop.cli.InputHandler; |
| import org.apache.fop.tools.anttasks.FileCompare; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import org.apache.commons.logging.impl.SimpleLog; |
| |
| /** |
| * TestConverter is used to process a set of tests specified in |
| * a testsuite. |
| * This class retrieves the data in the testsuite and uses FOP |
| * to convert the xml and xsl file into either an xml representation |
| * of the area tree or a pdf document. |
| * The area tree can be used for automatic comparisons between different |
| * versions of FOP or the pdf can be view for manual checking and |
| * pdf rendering. |
| */ |
| public class TestConverter { |
| |
| // configure fopFactory as desired |
| private FopFactory fopFactory = FopFactory.newInstance(); |
| |
| private boolean failOnly = false; |
| private String outputFormat = MimeConstants.MIME_FOP_AREA_TREE; |
| private File destdir; |
| private File compare = null; |
| private String baseDir = "./"; |
| private Map differ = new java.util.HashMap(); |
| |
| /** |
| * logging instance |
| */ |
| protected SimpleLog logger = null; |
| |
| /** |
| * This main method can be used to run the test converter from |
| * the command line. |
| * This will take a specified testsuite xml and process all |
| * tests in it. |
| * The command line options are: |
| * -b to set the base directory for where the testsuite and associated files are |
| * -failOnly to process only the tests which are specified as fail in the test results |
| * -pdf to output the result as pdf |
| * @param args command-line arguments |
| */ |
| public static void main(String[] args) { |
| if (args == null || args.length == 0) { |
| System.out.println("test suite file name required"); |
| } |
| TestConverter tc = new TestConverter(); |
| |
| String results = "results"; |
| String testFile = null; |
| for (int count = 0; count < args.length; count++) { |
| if (args[count].equals("-failOnly")) { |
| tc.setFailOnly(true); |
| } else if (args[count].equals("-pdf")) { |
| tc.setOutputFormat(MimeConstants.MIME_PDF); |
| } else if (args[count].equals("-rtf")) { |
| tc.setOutputFormat(MimeConstants.MIME_RTF); |
| } else if (args[count].equals("-ps")) { |
| tc.setOutputFormat(MimeConstants.MIME_POSTSCRIPT); |
| } else if (args[count].equals("-d")) { |
| tc.setDebug(true); |
| } else if (args[count].equals("-b")) { |
| tc.setBaseDir(args[++count]); |
| } else if (args[count].equals("-results")) { |
| results = args[++count]; |
| } else { |
| testFile = args[count]; |
| } |
| } |
| if (testFile == null) { |
| System.out.println("test suite file name required"); |
| } |
| |
| tc.runTests(testFile, results, null); |
| } |
| |
| /** |
| * Construct a new TestConverter |
| */ |
| public TestConverter() { |
| logger = new SimpleLog("FOP/Test"); |
| logger.setLevel(SimpleLog.LOG_LEVEL_ERROR); |
| } |
| |
| /** |
| * Controls output format to generate |
| * @param outputFormat the MIME type of the output format |
| */ |
| public void setOutputFormat(String outputFormat) { |
| this.outputFormat = outputFormat; |
| } |
| |
| /** |
| * Controls whether to process only the tests which are specified as fail |
| * in the test results. |
| * @param fail True if only fail tests should be processed |
| */ |
| public void setFailOnly(boolean fail) { |
| failOnly = fail; |
| } |
| |
| /** |
| * Sets the base directory. |
| * @param str base directory |
| */ |
| public void setBaseDir(String str) { |
| baseDir = str; |
| } |
| |
| /** |
| * Controls whether to set logging to debug level |
| * @param debug If true, debug level, if false, error level |
| */ |
| public void setDebug(boolean debug) { |
| if (debug) { |
| logger.setLevel(SimpleLog.LOG_LEVEL_DEBUG); |
| } else { |
| logger.setLevel(SimpleLog.LOG_LEVEL_ERROR); |
| } |
| } |
| |
| /** |
| * Run the Tests. |
| * This runs the tests specified in the xml file fname. |
| * The document is read as a dom and each testcase is covered. |
| * @param fname filename of the input file |
| * @param dest destination directory |
| * @param compDir comparison directory |
| * @return Map a Map containing differences |
| */ |
| public Map runTests(String fname, String dest, String compDir) { |
| logger.debug("running tests in file:" + fname); |
| try { |
| if (compDir != null) { |
| compare = new File(baseDir + "/" + compDir); |
| } |
| destdir = new File(baseDir + "/" + dest); |
| destdir.mkdirs(); |
| File f = new File(baseDir + "/" + fname); |
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| DocumentBuilder db = factory.newDocumentBuilder(); |
| Document doc = db.parse(f); |
| |
| NodeList suitelist = doc.getChildNodes(); |
| if (suitelist.getLength() == 0) { |
| return differ; |
| } |
| |
| Node testsuite = null; |
| testsuite = doc.getDocumentElement(); |
| |
| if (testsuite.hasAttributes()) { |
| String profile |
| = testsuite.getAttributes().getNamedItem("profile").getNodeValue(); |
| logger.debug("testing test suite:" + profile); |
| } |
| |
| NodeList testcases = testsuite.getChildNodes(); |
| for (int count = 0; count < testcases.getLength(); count++) { |
| Node testcase = testcases.item(count); |
| if (testcase.getNodeName().equals("testcases")) { |
| runTestCase(testcase); |
| } |
| } |
| } catch (Exception e) { |
| logger.error("Error while running tests", e); |
| } |
| return differ; |
| } |
| |
| /** |
| * Run a test case. |
| * This goes through a test case in the document. |
| * A testcase can contain a test, a result or more test cases. |
| * A test case is handled recursively otherwise the test is run. |
| * @param tcase Test case node to run |
| */ |
| protected void runTestCase(Node tcase) { |
| if (tcase.hasAttributes()) { |
| String profile |
| = tcase.getAttributes().getNamedItem("profile").getNodeValue(); |
| logger.debug("testing profile:" + profile); |
| } |
| |
| NodeList cases = tcase.getChildNodes(); |
| for (int count = 0; count < cases.getLength(); count++) { |
| Node node = cases.item(count); |
| String nodename = node.getNodeName(); |
| if (nodename.equals("testcases")) { |
| runTestCase(node); |
| } else if (nodename.equals("test")) { |
| runTest(tcase, node); |
| } else if (nodename.equals("result")) { |
| //nop |
| } |
| |
| } |
| |
| } |
| |
| /** |
| * Run a particular test. |
| * This runs a test defined by the xml and xsl documents. |
| * If the test has a result specified it is checked. |
| * This creates an XSLTInputHandler to provide the input |
| * for FOP and writes the data out to an XML are tree. |
| * @param testcase Test case to run |
| * @param test Test |
| */ |
| protected void runTest(Node testcase, Node test) { |
| String id = test.getAttributes().getNamedItem("id").getNodeValue(); |
| Node result = locateResult(testcase, id); |
| boolean pass = false; |
| if (result != null) { |
| String agreement |
| = result.getAttributes().getNamedItem("agreement").getNodeValue(); |
| pass = agreement.equals("full"); |
| } |
| |
| if (pass && failOnly) { |
| return; |
| } |
| |
| String xml = test.getAttributes().getNamedItem("xml").getNodeValue(); |
| Node xslNode = test.getAttributes().getNamedItem("xsl"); |
| String xsl = null; |
| if (xslNode != null) { |
| xsl = xslNode.getNodeValue(); |
| } |
| logger.debug("converting xml:" + xml + " and xsl:" |
| + xsl + " to area tree"); |
| |
| String res = xml; |
| Node resNode = test.getAttributes().getNamedItem("results"); |
| if (resNode != null) { |
| res = resNode.getNodeValue(); |
| } |
| try { |
| File xmlFile = new File(baseDir + "/" + xml); |
| String baseURL = null; |
| try { |
| baseURL = xmlFile.getParentFile().toURI().toURL().toExternalForm(); |
| } catch (Exception e) { |
| logger.error("Error setting base directory"); |
| } |
| |
| InputHandler inputHandler = null; |
| if (xsl == null) { |
| inputHandler = new InputHandler(xmlFile); |
| } else { |
| inputHandler = new InputHandler(xmlFile, |
| new File(baseDir + "/" |
| + xsl), null); |
| } |
| |
| FOUserAgent userAgent = fopFactory.newFOUserAgent(); |
| userAgent.setBaseURL(baseURL); |
| |
| userAgent.getRendererOptions().put("fineDetail", new Boolean(false)); |
| userAgent.getRendererOptions().put("consistentOutput", new Boolean(true)); |
| userAgent.setProducer("Testsuite Converter"); |
| |
| String outname = res; |
| if (outname.endsWith(".xml") || outname.endsWith(".pdf")) { |
| outname = outname.substring(0, outname.length() - 4); |
| } |
| File outputFile = new File(destdir, |
| outname + makeResultExtension()); |
| |
| outputFile.getParentFile().mkdirs(); |
| OutputStream outStream = new java.io.BufferedOutputStream( |
| new java.io.FileOutputStream(outputFile)); |
| logger.debug("ddir:" + destdir + " on:" + outputFile.getName()); |
| inputHandler.renderTo(userAgent, outputFormat, outStream); |
| outStream.close(); |
| |
| // check difference |
| if (compare != null) { |
| File f1 = new File(destdir, outname + ".at.xml"); |
| File f2 = new File(compare, outname + ".at.xml"); |
| if (!compareFiles(f1, f2)) { |
| differ.put(outname + ".at.xml", new Boolean(pass)); |
| } |
| } |
| } catch (Exception e) { |
| logger.error("Error while running tests", e); |
| } |
| } |
| |
| /** |
| * Return a suitable file extension for the output format. |
| */ |
| private String makeResultExtension() { |
| if (MimeConstants.MIME_PDF.equals(outputFormat)) { |
| return ".pdf"; |
| } else if (MimeConstants.MIME_RTF.equals(outputFormat)) { |
| return ".rtf"; |
| } else if (MimeConstants.MIME_POSTSCRIPT.equals(outputFormat)) { |
| return ".ps"; |
| } else { |
| return ".at.xml"; |
| } |
| } |
| |
| /** |
| * Compare files. |
| * @param f1 first file |
| * @param f2 second file |
| * @return true if equal |
| */ |
| protected boolean compareFiles(File f1, File f2) { |
| try { |
| return FileCompare.compareFiles(f1, f2); |
| } catch (Exception e) { |
| logger.error("Error while comparing files", e); |
| return false; |
| } |
| } |
| |
| private Node locateResult(Node testcase, String id) { |
| NodeList cases = testcase.getChildNodes(); |
| for (int count = 0; count < cases.getLength(); count++) { |
| Node node = cases.item(count); |
| String nodename = node.getNodeName(); |
| if (nodename.equals("result")) { |
| String resultid |
| = node.getAttributes().getNamedItem("id").getNodeValue(); |
| if (id.equals(resultid)) { |
| return node; |
| } |
| } |
| } |
| return null; |
| } |
| |
| } |