• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 
22 /*
23  *
24  * ProgrammaticDOMTest.java
25  *
26  */
27 package org.apache.qetest.xalanj2;
28 
29 import android.platform.test.annotations.FlakyTest;
30 import java.io.File;
31 import java.util.Properties;
32 
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.transform.Templates;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerFactory;
38 import javax.xml.transform.dom.DOMResult;
39 import javax.xml.transform.dom.DOMSource;
40 import javax.xml.transform.stream.StreamResult;
41 
42 import org.apache.qetest.FileBasedTest;
43 import org.apache.qetest.Logger;
44 import org.apache.qetest.OutputNameManager;
45 import org.apache.qetest.QetestUtils;
46 import org.apache.qetest.xsl.XSLTestfileInfo;
47 import org.junit.Test;
48 import org.w3c.dom.Document;
49 import org.w3c.dom.DocumentFragment;
50 import org.w3c.dom.Element;
51 import org.w3c.dom.Node;
52 import org.xml.sax.InputSource;
53 
54 //-------------------------------------------------------------------------
55 
56 /**
57  * Functionality/system/integration tests for DOMSource.
58  * Various kinds of DOM elements, documents used.
59  * @author shane_curcuru@lotus.com
60  * @version $Id$
61  */
62 public class ProgrammaticDOMTest extends FileBasedTest
63 {
64 
65     /** Provides nextName(), currentName() functionality.  */
66     protected OutputNameManager outNames;
67 
68     /** Simple DOMTest.xml/xsl file pair.  */
69     protected XSLTestfileInfo testFileInfo = new XSLTestfileInfo();
70 
71     /** Subdirectory under test\tests\api for our xsl/xml files.  */
72     public static final String TRAX_SUBDIR = File.separator + "trax" + File.separator;
73 
74     private static final String xslNamespace = "http://www.w3.org/1999/XSL/Transform";
75     private static final String nsNamespace = "http://www.w3.org/XML/1998/namespace";
76 
77     /** Just initialize test name, comment, numTestCases. */
ProgrammaticDOMTest()78     public ProgrammaticDOMTest()
79     {
80         numTestCases = 2;  // REPLACE_num
81         testName = "ProgrammaticDOMTest";
82         testComment = "Functionality/system/integration tests for DOMSource";
83     }
84 
85 
86     /**
87      * Initialize this test - Set names of xml/xsl test files.
88      *
89      * @param p Properties to initialize from (if needed)
90      * @return false if we should abort the test; true otherwise
91      */
doTestFileInit(Properties p)92     public boolean doTestFileInit(Properties p)
93     {
94         // Used for all tests; just dump files in trax subdir
95         File outSubDir = new File(outputDir + TRAX_SUBDIR);
96         if (!outSubDir.mkdirs())
97             reporter.logWarningMsg("Could not create output dir: " + outSubDir);
98         // Initialize an output name manager to that dir with .out extension
99         outNames = new OutputNameManager(outputDir + TRAX_SUBDIR
100                                          + testName, ".out");
101 
102         testFileInfo.inputName = QetestUtils.filenameToURL(inputDir
103                               + TRAX_SUBDIR + "identity.xsl");
104         testFileInfo.xmlName = QetestUtils.filenameToURL(inputDir
105                               + TRAX_SUBDIR + "identity.xml");
106         testFileInfo.goldName = goldDir + TRAX_SUBDIR + "identity.out";
107 
108         try
109         {
110             TransformerFactory tf = TransformerFactory.newInstance();
111             if (!(tf.getFeature(DOMSource.FEATURE)
112                   && tf.getFeature(DOMResult.FEATURE)))
113             {   // The rest of this test relies on DOM
114                 reporter.logErrorMsg("DOM*.FEATURE not supported! Some tests may be invalid!");
115             }
116         }
117         catch (Throwable t)
118         {
119             reporter.checkFail(
120                 "Problem creating factory; Some tests may be invalid!");
121             reporter.logThrowable(reporter.ERRORMSG, t,
122                                   "Problem creating factory; Some tests may be invalid!");
123         }
124 
125         return true;
126     }
127 
128 
129     /**
130      * Pass various forms of XML DOM's to a transform.
131      * Reproduce Bugzilla 1361.
132      * http://nagoya.apache.org/bugzilla/show_bug.cgi?id=1361
133      *
134      * @return false if we should abort the test; true otherwise
135      */
testCase1()136     public boolean testCase1()
137     {
138         reporter.testCaseInit("Pass various forms of XML DOM's to a transform");
139 
140         try
141         {
142             // Startup a factory and docbuilder, create some nodes/DOMs
143             DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
144             dfactory.setNamespaceAware(true);
145             DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
146 
147             reporter.logTraceMsg("parsing xml, xsl files");
148             Document xslDoc = docBuilder.parse(new InputSource(testFileInfo.inputName));
149             Document xmlDoc = docBuilder.parse(new InputSource(testFileInfo.xmlName));
150             TransformerFactory factory = TransformerFactory.newInstance();
151 
152             // Try a transform with XSL Document and XML Document (common usage)
153             Templates templates = factory.newTemplates(new DOMSource(xslDoc));
154             Transformer transformer = templates.newTransformer();
155             reporter.logInfoMsg("About to transform(xmlDoc, StreamResult(" + outNames.nextName() + "))");
156             transformer.transform(new DOMSource(xmlDoc), new StreamResult(outNames.currentName()));
157             fileChecker.check(reporter,
158                               new File(outNames.currentName()),
159                               new File(testFileInfo.goldName),
160                               "transform(xmlDoc,...) into " + outNames.currentName());
161 
162             // Programmatically build the XML file into a Document and transform
163             Document xmlBuiltDoc = docBuilder.newDocument();
164             appendIdentityDOMXML(xmlBuiltDoc, xmlBuiltDoc, true);
165             transformer = templates.newTransformer();
166             reporter.logInfoMsg("About to transform(xmlBuiltDoc, StreamResult(" + outNames.nextName() + "))");
167             transformer.transform(new DOMSource(xmlBuiltDoc), new StreamResult(outNames.currentName()));
168             fileChecker.check(reporter,
169                               new File(outNames.currentName()),
170                               new File(testFileInfo.goldName),
171                               "transform(xmlBuiltDoc,...) into " + outNames.currentName());
172 
173             // Again, with identity transformer
174             transformer = factory.newTransformer();
175             reporter.logInfoMsg("About to identityTransform(xmlBuiltDoc, StreamResult(" + outNames.nextName() + "))");
176             transformer.transform(new DOMSource(xmlBuiltDoc), new StreamResult(outNames.currentName()));
177             fileChecker.check(reporter,
178                               new File(outNames.currentName()),
179                               new File(testFileInfo.goldName),
180                               "identityTransform(xmlBuiltDoc,...) into " + outNames.currentName());
181 
182 
183             // Programmatically build the XML file into a DocFrag and transform
184             xmlBuiltDoc = docBuilder.newDocument();
185             DocumentFragment xmlBuiltDocFrag = xmlBuiltDoc.createDocumentFragment();
186             appendIdentityDOMXML(xmlBuiltDocFrag, xmlBuiltDoc, true);
187             transformer = templates.newTransformer();
188             reporter.logInfoMsg("About to transform(xmlBuiltDocFrag, StreamResult(" + outNames.nextName() + "))");
189             transformer.transform(new DOMSource(xmlBuiltDocFrag), new StreamResult(outNames.currentName()));
190             fileChecker.check(reporter,
191                               new File(outNames.currentName()),
192                               new File(testFileInfo.goldName),
193                               "transform(xmlBuiltDocFrag,...) into " + outNames.currentName());
194 
195             // Again, with identity transformer
196             transformer = factory.newTransformer();
197             reporter.logInfoMsg("About to identityTransform(xmlBuiltDocFrag, StreamResult(" + outNames.nextName() + "))");
198             transformer.transform(new DOMSource(xmlBuiltDocFrag), new StreamResult(outNames.currentName()));
199             fileChecker.check(reporter,
200                               new File(outNames.currentName()),
201                               new File(testFileInfo.goldName),
202                               "identityTransform(xmlBuiltDocFrag,...) into " + outNames.currentName());
203 
204 
205             // Programmatically build the XML file into an Element and transform
206             xmlBuiltDoc = docBuilder.newDocument();
207             // Note: Here, we implicitly already have the outer list
208             //  element, so ensure the worker method doesn't add again
209             Element xmlBuiltElem = xmlBuiltDoc.createElement("list");
210             appendIdentityDOMXML(xmlBuiltElem, xmlBuiltDoc, false);
211             transformer = templates.newTransformer();
212             reporter.logInfoMsg("About to transform(xmlBuiltElem, StreamResult(" + outNames.nextName() + "))");
213             transformer.transform(new DOMSource(xmlBuiltElem), new StreamResult(outNames.currentName()));
214             fileChecker.check(reporter,
215                               new File(outNames.currentName()),
216                               new File(testFileInfo.goldName),
217                               "transform(xmlBuiltElem,...) into " + outNames.currentName());
218 
219             // Again, with identity transformer
220             transformer = factory.newTransformer();
221             reporter.logInfoMsg("About to identityTransform(xmlBuiltElem, StreamResult(" + outNames.nextName() + "))");
222             transformer.transform(new DOMSource(xmlBuiltElem), new StreamResult(outNames.currentName()));
223             fileChecker.check(reporter,
224                               new File(outNames.currentName()),
225                               new File(testFileInfo.goldName),
226                               "identityTransform(xmlBuiltElem,...) into " + outNames.currentName());
227         }
228         catch (Throwable t)
229         {
230             reporter.checkFail("Problem with various XML elems/documents");
231             reporter.logThrowable(reporter.ERRORMSG, t, "Problem with various XML elems/documents");
232         }
233 
234         reporter.testCaseClose();
235         return true;
236     }
237 
238 
239     /**
240      * Build a stylesheet DOM programmatically and use it.
241      *
242      * @return false if we should abort the test; true otherwise
243      */
testCase2()244     public boolean testCase2()
245     {
246         reporter.testCaseInit("Build a stylesheet DOM programmatically and use it");
247 
248         try
249         {
250             // Startup a factory and docbuilder, create some nodes/DOMs
251             DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
252             dfactory.setNamespaceAware(true);
253             DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
254 
255             reporter.logTraceMsg("parsing xml file");
256             Document xmlDoc = docBuilder.parse(new InputSource(testFileInfo.xmlName));
257             TransformerFactory factory = TransformerFactory.newInstance();
258             Transformer transformer = null;
259 
260             // Programmatically build the XSL file into a Document and transform
261             Document xslBuiltDoc = docBuilder.newDocument();
262             appendIdentityDOMXSL(xslBuiltDoc, xslBuiltDoc, true);
263             // For debugging, write the generated stylesheet out
264             //  Note this will not textually exactly match the identity.xsl file
265             reporter.logInfoMsg("Writing out xslBuiltDoc to "+ outNames.nextName());
266             transformer = factory.newTransformer();
267             transformer.transform(new DOMSource(xslBuiltDoc), new StreamResult(outNames.currentName()));
268 
269             reporter.logInfoMsg("About to newTransformer(xslBuiltDoc)");
270             transformer = factory.newTransformer(new DOMSource(xslBuiltDoc));
271             reporter.logInfoMsg("About to transform(xmlDoc, StreamResult(" + outNames.nextName() + "))");
272             transformer.transform(new DOMSource(xmlDoc), new StreamResult(outNames.currentName()));
273             fileChecker.check(reporter,
274                               new File(outNames.currentName()),
275                               new File(testFileInfo.goldName),
276                               "transform(xslBuiltDoc,...) into " + outNames.currentName());
277 
278 
279             // Programmatically build the XSL file into a DocFrag and transform
280             xslBuiltDoc = docBuilder.newDocument();
281             DocumentFragment xslBuiltDocFrag = xslBuiltDoc.createDocumentFragment();
282             appendIdentityDOMXSL(xslBuiltDocFrag, xslBuiltDoc, true);
283             // For debugging, write the generated stylesheet out
284             reporter.logInfoMsg("Writing out xslBuiltDocFrag to "+ outNames.nextName());
285             transformer = factory.newTransformer();
286             transformer.transform(new DOMSource(xslBuiltDocFrag), new StreamResult(outNames.currentName()));
287 
288             reporter.logCriticalMsg("//@todo Verify that this is even a valid operation!");
289             reporter.logCriticalMsg("Bugzilla#5133 NPE below MOVED to SmoketestOuttakes.java 27-Nov-01 -sc");
290 /* @todo Bugzilla#5133 NPE below MOVED to SmoketestOuttakes.java 27-Nov-01 -sc
291 // Check that the DOM is actually correct, esp namespace nodes on top level
292 // java.lang.NullPointerException
293 //	at org.apache.xalan.transformer.TransformerImpl.createResultContentHandler(TransformerImpl.java, Compiled Code)
294 
295 
296             reporter.logInfoMsg("About to newTransformer(xslBuiltDocFrag)");
297             transformer = factory.newTransformer(new DOMSource(xslBuiltDocFrag));
298             reporter.logInfoMsg("About to transform(xmlDoc, StreamResult(" + outNames.nextName() + "))");
299             transformer.transform(new DOMSource(xmlDoc), new StreamResult(outNames.currentName()));
300             fileChecker.check(reporter,
301                               new File(outNames.currentName()),
302                               new File(testFileInfo.goldName),
303                               "transform(xslBuiltDocFrag,...) into " + outNames.currentName());
304 ** @todo Bugzilla#5133 NPE above MOVED to SmoketestOuttakes.java 27-Nov-01 -sc */
305         }
306         catch (Throwable t)
307         {
308             reporter.checkFail("Problem with various XSL1 elems/documents");
309             reporter.logThrowable(reporter.ERRORMSG, t, "Problem with various XSL1 elems/documents");
310         }
311 
312 /* @todo Bugzilla#5133 DOM003 Namespace error below MOVED to SmoketestOuttakes.java 27-Nov-01 -sc
313 //org.w3c.dom.DOMException: DOM003 Namespace error
314 //	at org.apache.xerces.dom.AttrNSImpl.<init>(AttrNSImpl.java:134)
315 //	at org.apache.xerces.dom.CoreDocumentImpl.createAttributeNS(CoreDocumentImpl.java:1363)
316 //	at org.apache.xerces.dom.ElementImpl.setAttributeNS(ElementImpl.java:596)
317 //	at org.apache.qetest.xalanj2.ProgrammaticDOMTest.testCase2(ProgrammaticDOMTest.java:355)
318 
319         try
320         {
321             // Startup a factory and docbuilder, create some nodes/DOMs
322             DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
323             dfactory.setNamespaceAware(true);
324             DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
325 
326             reporter.logTraceMsg("parsing xml file");
327             Document xmlDoc = docBuilder.parse(new InputSource(testFileInfo.xmlName));
328             TransformerFactory factory = TransformerFactory.newInstance();
329             Transformer transformer = null;
330 
331             // Programmatically build the XSL file into an Element and transform
332             Document xslBuiltDoc = docBuilder.newDocument();
333             // Note: Here, we implicitly already have the outer list
334             //  element, so ensure the worker method doesn't add again
335             Element xslBuiltElem = xslBuiltDoc.createElementNS(xslNamespace, "xsl:stylesheet");
336             xslBuiltElem.setAttributeNS(null, "version", "1.0");
337             xslBuiltElem.setAttributeNS(nsNamespace, "xmlns:xsl", xslNamespace);
338             appendIdentityDOMXSL(xslBuiltElem, xslBuiltDoc, false);
339             // For debugging, write the generated stylesheet out
340             reporter.logInfoMsg("Writing out xslBuiltElem to "+ outNames.nextName());
341             transformer = factory.newTransformer();
342             transformer.transform(new DOMSource(xslBuiltElem), new StreamResult(outNames.currentName()));
343 
344             reporter.logCriticalMsg("//@todo Verify that this is even a valid operation!");
345             reporter.logInfoMsg("About to newTransformer(xslBuiltElem)");
346             transformer = factory.newTransformer(new DOMSource(xslBuiltElem));
347             reporter.logInfoMsg("About to transform(xmlDoc, StreamResult(" + outNames.nextName() + "))");
348             transformer.transform(new DOMSource(xmlDoc), new StreamResult(outNames.currentName()));
349             fileChecker.check(reporter,
350                               new File(outNames.currentName()),
351                               new File(testFileInfo.goldName),
352                               "transform(xslBuiltElem,...) into " + outNames.currentName());
353         }
354         catch (Throwable t)
355         {
356             reporter.checkFail("Problem with various XSL2 elems/documents");
357             reporter.logThrowable(reporter.ERRORMSG, t, "Problem with various XSL2 elems/documents");
358         }
359 ** @todo Bugzilla#5133 DOM003 Namespace error above MOVED to SmoketestOuttakes.java 27-Nov-01 -sc */
360 
361         reporter.testCaseClose();
362         return true;
363     }
364 
365 
366     /**
367      * Adds identity.xml elems to Node passed in.
368      * Subject to change; hackish for now
369      * @author curcuru
370      * @param n Node to append DOM elems to
371      * @param factory Document providing createElement, etc. services
372      * @param useOuterElem if we should append the top-level <list> elem
373      */
appendIdentityDOMXML(Node n, Document factory, boolean useOuterElem)374     public void appendIdentityDOMXML(Node n, Document factory, boolean useOuterElem)
375     {
376         try
377         {
378             Node container = null;
379             if (useOuterElem)
380             {
381                 // If asked to, create and append top-level <list>
382                 container = factory.createElement("list");
383                 n.appendChild(container);
384             }
385             else
386             {
387                 // Otherwise, just use their Node
388                 container = n;
389             }
390             container.appendChild(factory.createTextNode("\n  "));
391 
392             Element elemItem = factory.createElement("item");
393             elemItem.appendChild(factory.createTextNode("Xalan-J 1.x"));
394             container.appendChild(elemItem);
395             container.appendChild(factory.createTextNode("\n  "));
396 
397             elemItem = factory.createElement("item");
398             elemItem.appendChild(factory.createTextNode("Xalan-J 2.x"));
399             container.appendChild(elemItem);
400             container.appendChild(factory.createTextNode("\n  "));
401 
402             elemItem = factory.createElement("item");
403             elemItem.appendChild(factory.createTextNode("Xalan-C 1.x"));
404             container.appendChild(elemItem);
405             container.appendChild(factory.createTextNode("\n  "));
406 
407             Element elemInnerList = factory.createElement("list");
408             container.appendChild(elemInnerList);
409             elemInnerList.appendChild(factory.createTextNode("\n    "));
410 
411             elemItem = factory.createElement("item");
412             elemItem.appendChild(factory.createTextNode("Xalan documentation"));
413             elemInnerList.appendChild(elemItem);
414             elemInnerList.appendChild(factory.createTextNode("\n    "));
415 
416             elemItem = factory.createElement("item");
417             elemItem.appendChild(factory.createTextNode("Xalan tests"));
418             elemInnerList.appendChild(elemItem);
419             elemInnerList.appendChild(factory.createTextNode("\n  "));
420 
421             container.appendChild(factory.createTextNode("\n"));
422         }
423         catch (Exception e)
424         {
425             reporter.logErrorMsg("appendDOMTestXML threw: " + e.toString());
426             reporter.logThrowable(Logger.ERRORMSG, e, "appendDOMTestXML threw");
427         }
428     }
429 
430 
431     /**
432      * Adds identity.xsl elems to Node passed in.
433      * Subject to change; hackish for now
434      * @author curcuru
435      * @param n Node to append DOM elems to
436      * @param factory Document providing createElement, etc. services
437      * @param useOuterElem if we should append the top-level <stylesheet> elem
438      */
appendIdentityDOMXSL(Node n, Document factory, boolean useOuterElem)439     public void appendIdentityDOMXSL(Node n, Document factory, boolean useOuterElem)
440     {
441         try
442         {
443             /// <xsl:template match="@*|node()">
444             Element template = factory.createElementNS(xslNamespace, "xsl:template");
445             template.setAttributeNS(null, "match", "@*|node()");
446 
447             /// <xsl:copy>
448             Element copyElem = factory.createElementNS(xslNamespace, "xsl:copy");
449 
450             /// <xsl:apply-templates select="@*|node()"/>
451             Element applyTemplatesElem = factory.createElementNS(xslNamespace, "xsl:apply-templates");
452             applyTemplatesElem.setAttributeNS(null, "select", "@*|node()");
453 
454             // Stick it all together with faked-up newlines for readability
455             copyElem.appendChild(factory.createTextNode("\n    "));
456             copyElem.appendChild(applyTemplatesElem);
457             copyElem.appendChild(factory.createTextNode("\n  "));
458 
459             template.appendChild(factory.createTextNode("\n  "));
460             template.appendChild(copyElem);
461             template.appendChild(factory.createTextNode("\n"));
462 
463 
464             if (useOuterElem)
465             {
466                 // If asked to, create and append top-level <stylesheet> elem
467                 /// <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
468                 Element stylesheetElem = factory.createElementNS(xslNamespace, "xsl:stylesheet");
469                 stylesheetElem.setAttributeNS(null, "version", "1.0");
470 
471                 // Following is not officially needed by the DOM,  but may help
472                 // less-sophisticated DOM readers downstream
473                 // Removed due to DOM003 Namespace error
474                 // stylesheetElem.setAttributeNS(nsNamespace, "xmlns:xsl", xslNamespace);
475                 stylesheetElem.appendChild(template);
476                 n.appendChild(stylesheetElem);
477             }
478             else
479             {
480                 // Otherwise, just use their Node
481                 n.appendChild(template);
482             }
483 
484         }
485         catch (Exception e)
486         {
487             reporter.logErrorMsg("appendIdentityDOMXSL threw: " + e.toString());
488             reporter.logThrowable(Logger.ERRORMSG, e, "appendIdentityDOMXSL threw");
489         }
490     }
491 
492 
493     /**
494      * Convenience method to print out usage information - update if needed.
495      * @return String denoting usage of this test class
496      */
usage()497     public String usage()
498     {
499         return ("Common [optional] options supported by ProgrammaticDOMTest:\n"
500                 + "(Note: assumes inputDir=.\\tests\\api)\n"
501                 + "REPLACE_any_new_test_arguments\n"
502                 + super.usage());   // Grab our parent classes usage as well
503     }
504 
505 
506     /**
507      * Main method to run test from the command line - can be left alone.
508      * @param args command line argument array
509      */
main(String[] args)510     public static void main(String[] args)
511     {
512         ProgrammaticDOMTest app = new ProgrammaticDOMTest();
513         app.doMain(args);
514     }
515 
516     // Android-added: Run main method as a JUnit test case.
517     @FlakyTest(bugId = 292520220)
518     @Test
main()519     public void main() {
520         main(new String[0]);
521     }
522 }
523