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.

TestConverter.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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.tools;
  19. import java.io.File;
  20. import java.io.OutputStream;
  21. import java.net.URI;
  22. import java.util.Map;
  23. import javax.xml.parsers.DocumentBuilder;
  24. import javax.xml.parsers.DocumentBuilderFactory;
  25. import org.w3c.dom.Document;
  26. import org.w3c.dom.Node;
  27. import org.w3c.dom.NodeList;
  28. import org.apache.commons.io.IOUtils;
  29. import org.apache.commons.logging.impl.SimpleLog;
  30. import org.apache.fop.apps.FOUserAgent;
  31. import org.apache.fop.apps.FopFactory;
  32. import org.apache.fop.apps.MimeConstants;
  33. import org.apache.fop.cli.InputHandler;
  34. import org.apache.fop.tools.anttasks.FileCompare;
  35. /**
  36. * TestConverter is used to process a set of tests specified in
  37. * a testsuite.
  38. * This class retrieves the data in the testsuite and uses FOP
  39. * to convert the xml and xsl file into either an xml representation
  40. * of the area tree or a pdf document.
  41. * The area tree can be used for automatic comparisons between different
  42. * versions of FOP or the pdf can be view for manual checking and
  43. * pdf rendering.
  44. */
  45. public class TestConverter {
  46. private boolean failOnly;
  47. private String outputFormat = MimeConstants.MIME_FOP_AREA_TREE;
  48. private File destdir;
  49. private File compare;
  50. private String baseDir = "./";
  51. private Map differ = new java.util.HashMap();
  52. /**
  53. * logging instance
  54. */
  55. protected SimpleLog logger;
  56. /**
  57. * This main method can be used to run the test converter from
  58. * the command line.
  59. * This will take a specified testsuite xml and process all
  60. * tests in it.
  61. * The command line options are:
  62. * -b to set the base directory for where the testsuite and associated files are
  63. * -failOnly to process only the tests which are specified as fail in the test results
  64. * -pdf to output the result as pdf
  65. * @param args command-line arguments
  66. */
  67. public static void main(String[] args) {
  68. if (args == null || args.length == 0) {
  69. System.out.println("test suite file name required");
  70. return;
  71. }
  72. TestConverter tc = new TestConverter();
  73. String results = "results";
  74. String testFile = null;
  75. for (int count = 0; count < args.length; count++) {
  76. if (args[count].equals("-failOnly")) {
  77. tc.setFailOnly(true);
  78. } else if (args[count].equals("-pdf")) {
  79. tc.setOutputFormat(MimeConstants.MIME_PDF);
  80. } else if (args[count].equals("-rtf")) {
  81. tc.setOutputFormat(MimeConstants.MIME_RTF);
  82. } else if (args[count].equals("-ps")) {
  83. tc.setOutputFormat(MimeConstants.MIME_POSTSCRIPT);
  84. } else if (args[count].equals("-d")) {
  85. tc.setDebug(true);
  86. } else if (args[count].equals("-b")) {
  87. tc.setBaseDir(args[++count]);
  88. } else if (args[count].equals("-results")) {
  89. results = args[++count];
  90. } else {
  91. testFile = args[count];
  92. }
  93. }
  94. if (testFile == null) {
  95. System.out.println("test suite file name required");
  96. }
  97. tc.runTests(testFile, results, null);
  98. }
  99. /**
  100. * Construct a new TestConverter
  101. */
  102. public TestConverter() {
  103. logger = new SimpleLog("FOP/Test");
  104. logger.setLevel(SimpleLog.LOG_LEVEL_ERROR);
  105. }
  106. /**
  107. * Controls output format to generate
  108. * @param outputFormat the MIME type of the output format
  109. */
  110. public void setOutputFormat(String outputFormat) {
  111. this.outputFormat = outputFormat;
  112. }
  113. /**
  114. * Controls whether to process only the tests which are specified as fail
  115. * in the test results.
  116. * @param fail True if only fail tests should be processed
  117. */
  118. public void setFailOnly(boolean fail) {
  119. failOnly = fail;
  120. }
  121. /**
  122. * Sets the base directory.
  123. * @param str base directory
  124. */
  125. public void setBaseDir(String str) {
  126. baseDir = str;
  127. }
  128. /**
  129. * Controls whether to set logging to debug level
  130. * @param debug If true, debug level, if false, error level
  131. */
  132. public void setDebug(boolean debug) {
  133. if (debug) {
  134. logger.setLevel(SimpleLog.LOG_LEVEL_DEBUG);
  135. } else {
  136. logger.setLevel(SimpleLog.LOG_LEVEL_ERROR);
  137. }
  138. }
  139. /**
  140. * Run the Tests.
  141. * This runs the tests specified in the xml file fname.
  142. * The document is read as a dom and each testcase is covered.
  143. * @param fname filename of the input file
  144. * @param dest destination directory
  145. * @param compDir comparison directory
  146. * @return Map a Map containing differences
  147. */
  148. public Map runTests(String fname, String dest, String compDir) {
  149. logger.debug("running tests in file:" + fname);
  150. try {
  151. if (compDir != null) {
  152. compare = new File(baseDir + "/" + compDir);
  153. }
  154. destdir = new File(baseDir + "/" + dest);
  155. destdir.mkdirs();
  156. File f = new File(baseDir + "/" + fname);
  157. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  158. DocumentBuilder db = factory.newDocumentBuilder();
  159. Document doc = db.parse(f);
  160. NodeList suitelist = doc.getChildNodes();
  161. if (suitelist.getLength() == 0) {
  162. return differ;
  163. }
  164. Node testsuite = null;
  165. testsuite = doc.getDocumentElement();
  166. if (testsuite.hasAttributes()) {
  167. String profile
  168. = testsuite.getAttributes().getNamedItem("profile").getNodeValue();
  169. logger.debug("testing test suite:" + profile);
  170. }
  171. NodeList testcases = testsuite.getChildNodes();
  172. for (int count = 0; count < testcases.getLength(); count++) {
  173. Node testcase = testcases.item(count);
  174. if (testcase.getNodeName().equals("testcases")) {
  175. runTestCase(testcase);
  176. }
  177. }
  178. } catch (Exception e) {
  179. logger.error("Error while running tests", e);
  180. }
  181. return differ;
  182. }
  183. /**
  184. * Run a test case.
  185. * This goes through a test case in the document.
  186. * A testcase can contain a test, a result or more test cases.
  187. * A test case is handled recursively otherwise the test is run.
  188. * @param tcase Test case node to run
  189. */
  190. protected void runTestCase(Node tcase) {
  191. if (tcase.hasAttributes()) {
  192. String profile
  193. = tcase.getAttributes().getNamedItem("profile").getNodeValue();
  194. logger.debug("testing profile:" + profile);
  195. }
  196. NodeList cases = tcase.getChildNodes();
  197. for (int count = 0; count < cases.getLength(); count++) {
  198. Node node = cases.item(count);
  199. String nodename = node.getNodeName();
  200. if (nodename.equals("testcases")) {
  201. runTestCase(node);
  202. } else if (nodename.equals("test")) {
  203. runTest(tcase, node);
  204. } /* else if (nodename.equals("result")) {
  205. //nop
  206. } */
  207. }
  208. }
  209. /**
  210. * Run a particular test.
  211. * This runs a test defined by the xml and xsl documents.
  212. * If the test has a result specified it is checked.
  213. * This creates an XSLTInputHandler to provide the input
  214. * for FOP and writes the data out to an XML are tree.
  215. * @param testcase Test case to run
  216. * @param test Test
  217. */
  218. protected void runTest(Node testcase, Node test) {
  219. String id = test.getAttributes().getNamedItem("id").getNodeValue();
  220. Node result = locateResult(testcase, id);
  221. boolean pass = false;
  222. if (result != null) {
  223. String agreement
  224. = result.getAttributes().getNamedItem("agreement").getNodeValue();
  225. pass = agreement.equals("full");
  226. }
  227. if (pass && failOnly) {
  228. return;
  229. }
  230. String xml = test.getAttributes().getNamedItem("xml").getNodeValue();
  231. Node xslNode = test.getAttributes().getNamedItem("xsl");
  232. String xsl = null;
  233. if (xslNode != null) {
  234. xsl = xslNode.getNodeValue();
  235. }
  236. logger.debug("converting xml:" + xml + " and xsl:"
  237. + xsl + " to area tree");
  238. String res = xml;
  239. Node resNode = test.getAttributes().getNamedItem("results");
  240. if (resNode != null) {
  241. res = resNode.getNodeValue();
  242. }
  243. try {
  244. File xmlFile = new File(baseDir + "/" + xml);
  245. URI baseUri = xmlFile.getParentFile().toURI();
  246. InputHandler inputHandler = null;
  247. if (xsl == null) {
  248. inputHandler = new InputHandler(xmlFile);
  249. } else {
  250. inputHandler = new InputHandler(xmlFile, new File(baseDir + "/" + xsl), null);
  251. }
  252. FopFactory fopFactory = FopFactory.newInstance(baseUri);
  253. FOUserAgent userAgent = fopFactory.newFOUserAgent();
  254. userAgent.getRendererOptions().put("fineDetail", false);
  255. userAgent.getRendererOptions().put("consistentOutput", true);
  256. userAgent.setProducer("Testsuite Converter");
  257. String outname = res;
  258. if (outname.endsWith(".xml") || outname.endsWith(".pdf")) {
  259. outname = outname.substring(0, outname.length() - 4);
  260. }
  261. File outputFile = new File(destdir,
  262. outname + makeResultExtension());
  263. outputFile.getParentFile().mkdirs();
  264. OutputStream outStream = null;
  265. try {
  266. outStream = new java.io.BufferedOutputStream(
  267. new java.io.FileOutputStream(outputFile));
  268. logger.debug("ddir:" + destdir + " on:" + outputFile.getName());
  269. inputHandler.renderTo(userAgent, outputFormat, outStream);
  270. } finally {
  271. IOUtils.closeQuietly(outStream);
  272. }
  273. // check difference
  274. if (compare != null) {
  275. File f1 = new File(destdir, outname + ".at.xml");
  276. File f2 = new File(compare, outname + ".at.xml");
  277. if (!compareFiles(f1, f2)) {
  278. differ.put(outname + ".at.xml", pass);
  279. }
  280. }
  281. } catch (Exception e) {
  282. logger.error("Error while running tests", e);
  283. }
  284. }
  285. /**
  286. * Return a suitable file extension for the output format.
  287. */
  288. private String makeResultExtension() {
  289. if (MimeConstants.MIME_PDF.equals(outputFormat)) {
  290. return ".pdf";
  291. } else if (MimeConstants.MIME_RTF.equals(outputFormat)) {
  292. return ".rtf";
  293. } else if (MimeConstants.MIME_POSTSCRIPT.equals(outputFormat)) {
  294. return ".ps";
  295. } else {
  296. return ".at.xml";
  297. }
  298. }
  299. /**
  300. * Compare files.
  301. * @param f1 first file
  302. * @param f2 second file
  303. * @return true if equal
  304. */
  305. protected boolean compareFiles(File f1, File f2) {
  306. try {
  307. return FileCompare.compareFiles(f1, f2);
  308. } catch (Exception e) {
  309. logger.error("Error while comparing files", e);
  310. return false;
  311. }
  312. }
  313. private Node locateResult(Node testcase, String id) {
  314. NodeList cases = testcase.getChildNodes();
  315. for (int count = 0; count < cases.getLength(); count++) {
  316. Node node = cases.item(count);
  317. String nodename = node.getNodeName();
  318. if (nodename.equals("result")) {
  319. String resultid
  320. = node.getAttributes().getNamedItem("id").getNodeValue();
  321. if (id.equals(resultid)) {
  322. return node;
  323. }
  324. }
  325. }
  326. return null;
  327. }
  328. }