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 // This file uses 2 space indents, no tabs. 22 23 /* 24 * 25 * TestXPathAPI.java 26 * 27 */ 28 package org.apache.qetest.xalanj2; 29 30 import android.platform.test.annotations.FlakyTest; 31 import java.io.File; 32 import java.io.FileInputStream; 33 import java.util.Properties; 34 35 import javax.xml.parsers.DocumentBuilderFactory; 36 import javax.xml.transform.OutputKeys; 37 import javax.xml.transform.Transformer; 38 import javax.xml.transform.TransformerException; 39 import javax.xml.transform.TransformerFactory; 40 import javax.xml.transform.dom.DOMSource; 41 import javax.xml.transform.stream.StreamResult; 42 43 import org.apache.qetest.FileBasedTest; 44 import org.apache.qetest.OutputNameManager; 45 import org.apache.qetest.xsl.XSLTestfileInfo; 46 import org.apache.test.android.AndroidFileUtils; 47 import org.apache.xml.dtm.DTM; 48 import org.apache.xml.dtm.DTMIterator; 49 import org.apache.xml.dtm.DTMManager; 50 import org.apache.xml.utils.PrefixResolverDefault; 51 import org.apache.xpath.XPathAPI; 52 import org.apache.xpath.objects.XObject; 53 import org.junit.Test; 54 import org.w3c.dom.Document; 55 import org.w3c.dom.DocumentFragment; 56 import org.w3c.dom.Node; 57 import org.w3c.dom.NodeList; 58 import org.w3c.dom.traversal.NodeIterator; 59 import org.xml.sax.InputSource; 60 61 /** 62 * Basic functionality test of the public XPathAPI methods. 63 * 64 * Very basic coverage/smoketest level test. 65 * Applies a number of XPaths to some sample documents 66 * and checks output from the various public XPathAPI mehods. 67 * @see XPathAPI 68 * @author myriam_midy@lotus.com 69 * @author shane_curcuru@lotus.com 70 */ 71 public class TestXPathAPI extends FileBasedTest 72 { 73 /** Array of sample XPaths to test. */ 74 protected String[] xpath; 75 76 /** Base path/name of all output files. */ 77 protected String baseOutName = null; 78 79 protected XSLTestfileInfo testFileInfo1 = new XSLTestfileInfo(); 80 protected XSLTestfileInfo testFileInfo2 = new XSLTestfileInfo(); 81 protected XSLTestfileInfo testFileInfo3 = new XSLTestfileInfo(); 82 protected XSLTestfileInfo testFileInfo4 = new XSLTestfileInfo(); 83 protected XSLTestfileInfo testFileInfo5 = new XSLTestfileInfo(); 84 protected XSLTestfileInfo testFileInfo6 = new XSLTestfileInfo(); 85 protected XSLTestfileInfo testFileInfo7 = new XSLTestfileInfo(); 86 87 88 /** Provides nextName(), currentName() functionality. */ 89 protected OutputNameManager outNames; 90 91 /** Subdirectory under test\tests\api for our xsl/xml files. */ 92 public static final String X2J_SUBDIR = "xalanj2"; 93 94 /** Just initialize test name, comment, numTestCases. */ TestXPathAPI()95 public TestXPathAPI() 96 { 97 numTestCases = 7; // REPLACE_num 98 testName = "TestXPathAPI"; 99 testComment = "API coverage testing of XPathAPI"; 100 } 101 102 /** 103 * Initialize this test - Set names of xml/xsl test files etc. 104 * Also initializes an array of sample xpaths to test. 105 * 106 * @param p Properties to initialize from (if needed) 107 * @return false if we should abort the test; true otherwise 108 */ doTestFileInit(Properties p)109 public boolean doTestFileInit(Properties p) 110 { 111 // Used for all tests; just dump files in trax subdir 112 File outSubDir = new File(outputDir + File.separator + X2J_SUBDIR); 113 if (!outSubDir.mkdirs()) 114 reporter.logWarningMsg("Could not create output dir: " + outSubDir); 115 // Output name manager initialized in each testCase 116 baseOutName = outputDir + File.separator + X2J_SUBDIR + File.separator + testName; 117 118 String testBasePath = inputDir 119 + File.separator 120 + X2J_SUBDIR 121 + File.separator; 122 String goldBasePath = goldDir 123 + File.separator 124 + X2J_SUBDIR 125 + File.separator; 126 127 // Gold names are appended onto for each test 128 testFileInfo1.xmlName = testBasePath + "testXPath.xml"; 129 testFileInfo1.goldName = goldBasePath; 130 131 testFileInfo2.xmlName = testBasePath + "testXPath.xml"; 132 testFileInfo2.goldName = goldBasePath; 133 134 testFileInfo3.xmlName = testBasePath + "testXPath.xml"; 135 testFileInfo3.goldName = goldBasePath; 136 137 testFileInfo4.xmlName = testBasePath + "testXPath.xml"; 138 testFileInfo4.goldName = goldBasePath; 139 140 testFileInfo5.xmlName = testBasePath + "testXPath.xml"; 141 testFileInfo5.goldName = goldBasePath; 142 143 testFileInfo6.xmlName = testBasePath + "testXPath2.xml"; 144 testFileInfo6.goldName = goldBasePath; 145 146 testFileInfo7.xmlName = testBasePath + "testXPath3.xml"; 147 testFileInfo7.goldName = goldBasePath; 148 149 // Initialize xpath test data 150 // Note: when adding new xpaths, update array ctor and 151 // also need to update each testCase's gold files 152 xpath = new String[25]; 153 xpath[0] = "/doc/a/@test"; 154 xpath[1] = "//."; 155 xpath[2] = "/doc"; 156 xpath[3] = "/doc/a"; 157 xpath[4] = "//@*"; 158 xpath[5] = "."; 159 xpath[6] = "//ancestor-or-self::*"; 160 xpath[7] = "./child::*[1]"; 161 xpath[8] = "//descendant-or-self::*/@*[1]"; 162 xpath[9] = "//@* | * | node()"; 163 xpath[10] = "//*"; 164 xpath[11] = "/doc/namespace::*"; 165 xpath[12] = "//descendant::comment()"; 166 xpath[13] = "//*[local-name()='a']"; 167 xpath[14] = "//*[current()]/@*"; 168 xpath[15] = "//*[last()]"; 169 xpath[16] = "doc/*[last()]"; 170 xpath[17] = "/doc/a/*[current()]/@*"; 171 xpath[18] = "doc/descendant::node()"; 172 xpath[19] = "doc/a/@*"; 173 xpath[20] = "doc/b/a/ancestor-or-self::*"; 174 xpath[21] = "doc/b/a/preceding::*"; 175 xpath[22] = "doc/a/following::*"; 176 xpath[23] = "/doc/b/preceding-sibling::*"; 177 xpath[24] = "/doc/a/following-sibling::*"; 178 179 return true; 180 } 181 182 183 184 /** Quick test of XPathAPI.selectNodeIterator(). */ testCase1()185 public boolean testCase1() 186 throws Exception 187 { 188 reporter.testCaseInit("Quick test of XPathAPI.selectNodeIterator()"); 189 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 190 191 Document doc = parseToDOM(testFileInfo1.xmlName); 192 Transformer serializer = getSerializer(); 193 194 for (int i=0;i<xpath.length; i++) 195 { 196 // Use the simple XPath API to select a nodeIterator. 197 NodeIterator nl = XPathAPI.selectNodeIterator(doc, xpath[i]); 198 199 Node n; 200 while ((n = nl.nextNode())!= null) 201 { 202 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 203 File f = new File(outNames.currentName()); 204 fileChecker.check(reporter, 205 f, 206 new File(testFileInfo1.goldName + f.getName()), 207 "selectNodeIterator() of "+xpath[i] + " into " + outNames.currentName()); 208 } 209 } // of for... 210 reporter.testCaseClose(); 211 return true; 212 } 213 214 /** Quick test of XPathAPI.selectNodeList(). */ testCase2()215 public boolean testCase2() 216 throws Exception 217 { 218 reporter.testCaseInit("Quick test of XPathAPI.selectNodeList()"); 219 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 220 221 // Note: parsed file and gold file don't match - why? 10-Oct-01 -sc 222 Document doc = parseToDOM(testFileInfo1.xmlName); 223 Transformer serializer = getSerializer(); 224 225 for (int i=0;i<xpath.length; i++) 226 { 227 NodeList nl = XPathAPI.selectNodeList(doc, xpath[i]); 228 229 Node n; 230 int j = 0; 231 while (j < nl.getLength()) 232 { 233 n = nl.item(j++); 234 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 235 File f = new File(outNames.currentName()); 236 fileChecker.check(reporter, 237 f, 238 new File(testFileInfo2.goldName + f.getName()), 239 "selectNodeList() of "+xpath[i] + " into " + outNames.currentName()); 240 } 241 } // of for... 242 reporter.testCaseClose(); 243 return true; 244 } 245 246 /** Quick test of XPathAPI.selectSingleNode(). */ testCase3()247 public boolean testCase3() 248 throws Exception 249 { 250 reporter.testCaseInit("Quick test of XPathAPI.selectSingleNode()"); 251 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 252 253 // Note: parsed file and gold file don't match - why? 10-Oct-01 -sc 254 Document doc = parseToDOM(testFileInfo1.xmlName); 255 Transformer serializer = getSerializer(); 256 257 for (int i=0;i<xpath.length; i++) 258 { 259 Node n = XPathAPI.selectSingleNode(doc, xpath[i]); 260 261 if (n != null) 262 { 263 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 264 File f = new File(outNames.currentName()); 265 fileChecker.check(reporter, 266 f, 267 new File(testFileInfo3.goldName + f.getName()), 268 "selectSingleNode() of "+xpath[i] + " into " + outNames.currentName()); 269 } 270 else 271 { 272 reporter.logWarningMsg("No node found with selectSingleNode() of "+xpath[i]); 273 } 274 } // of for... 275 reporter.testCaseClose(); 276 return true; 277 } 278 279 280 /** Quick test of XPathAPI.eval(). */ testCase4()281 public boolean testCase4() 282 throws Exception 283 { 284 reporter.testCaseInit("Quick test of XPathAPI.eval()"); 285 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 286 287 // Note: parsed file and gold file don't match - why? 10-Oct-01 -sc 288 Document doc = parseToDOM(testFileInfo1.xmlName); 289 Transformer serializer = getSerializer(); 290 291 //Document d1 =(Document) doc.getDocumentElement(); 292 // Node d = (doc.getNodeType() == Node.DOCUMENT_NODE) 293 // ? (Document) doc.getDocumentElement() : doc; 294 reporter.logInfoMsg("Creating a PrefixResolverDefault(...)"); 295 PrefixResolverDefault prefixResolver = 296 new PrefixResolverDefault(doc.getDocumentElement()); 297 298 for (int i=0;i<xpath.length; i++) 299 { 300 XObject list = XPathAPI.eval(doc, xpath[i], prefixResolver); 301 302 int n; 303 DTMIterator nl = list.iter(); 304 DTMManager dtmManager = nl.getDTMManager(); 305 while ((n = nl.nextNode())!= DTM.NULL) 306 { 307 Node node = dtmManager.getDTM(n).getNode(n); 308 serializer.transform(new DOMSource(node), new StreamResult(outNames.nextName())); 309 File f = new File(outNames.currentName()); 310 fileChecker.check(reporter, 311 f, 312 new File(testFileInfo4.goldName + f.getName()), 313 "eval() of "+xpath[i] + " into " + outNames.currentName()); 314 } 315 } // of for... 316 reporter.testCaseClose(); 317 return true; 318 } 319 320 /** Quick test of XPathAPI.selectNodeList() and doc.getFirstChild(). */ testCase5()321 public boolean testCase5() 322 throws Exception 323 { 324 reporter.testCaseInit("Quick test of XPathAPI.selectNodeList() and doc.getFirstChild()"); 325 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 326 327 Document doc = parseToDOM(testFileInfo5.xmlName); 328 Transformer serializer = getSerializer(); 329 330 // Use the simple XPath API to select a nodeIterator. 331 reporter.logStatusMsg("Querying DOM using selectNodeList(doc.getFirstChild(), 'a')"); 332 NodeList nl = XPathAPI.selectNodeList(doc.getFirstChild(), "a"); 333 334 Node n; 335 int j = 0; 336 while (j < nl.getLength()) 337 { 338 n = nl.item(j++); 339 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 340 File f = new File(outNames.currentName()); 341 fileChecker.check(reporter, 342 f, 343 new File(testFileInfo5.goldName + f.getName()), 344 "selectNodeList(doc.getFirstChild(), 'a') into " + outNames.currentName()); 345 } 346 reporter.testCaseClose(); 347 return true; 348 } 349 350 /** Quick test of XPathAPI.selectNodeIterator() and non-document node. */ testCase6()351 public boolean testCase6() 352 throws Exception 353 { 354 reporter.testCaseInit("Quick test of XPathAPI.selectNodeIterator() and non-document node"); 355 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 356 String filename = testFileInfo6.xmlName; 357 String xpathStr = "*[local-name()='sitemap' and namespace-uri()='http://apache.org/xalan/test/sitemap']"; 358 359 // Set up a DOM tree to query. 360 reporter.logInfoMsg("Parsing input file "+filename); 361 // Android-added: Look up the file in the java resources. 362 // InputSource in = new InputSource(new FileInputStream(filename)); 363 InputSource in = new InputSource(AndroidFileUtils.getInputFileUrl(filename).openStream()); 364 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 365 dfactory.setNamespaceAware(true); 366 Document doc = dfactory.newDocumentBuilder().parse(in); 367 368 Transformer serializer = getSerializer(); 369 370 // Create DocumentFragment 371 DocumentFragment frag = doc.createDocumentFragment(); 372 frag.appendChild(doc.getFirstChild()); 373 374 // Use the simple XPath API to select a nodeIterator. 375 reporter.logStatusMsg("selectNodeIterator(" + xpathStr + ") and a non document node"); 376 NodeIterator nl = XPathAPI.selectNodeIterator(frag, xpathStr); 377 378 Node n; 379 while ((n = nl.nextNode())!= null) 380 { 381 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 382 File f = new File(outNames.currentName()); 383 fileChecker.check(reporter, 384 f, 385 new File(testFileInfo6.goldName + f.getName()), 386 "selectNodeIterator(...) into " + outNames.currentName()); 387 } 388 reporter.testCaseClose(); 389 return true; 390 } 391 392 /** Quick test of XPathAPI.selectNodeList using 'id(a)'. */ testCase7()393 public boolean testCase7() 394 throws Exception 395 { 396 reporter.testCaseInit("Quick test of XPathAPI.selectNodeList using 'id(a)'"); 397 outNames = new OutputNameManager(baseOutName + reporter.getCurrentCaseNum(), ".out"); 398 399 // Note: parsed file and gold file don't match - why? 10-Oct-01 -sc 400 Document doc = parseToDOM(testFileInfo7.xmlName); 401 Transformer serializer = getSerializer(); 402 403 // Use the simple XPath API to select a nodeIterator. 404 reporter.logStatusMsg("selectNodeList using 'id(a)' "); 405 NodeList nl = XPathAPI.selectNodeList(doc, "id('a')"); 406 407 Node n; 408 int j = 0; 409 while (j < nl.getLength()) 410 { 411 n = nl.item(j++); 412 serializer.transform(new DOMSource(n), new StreamResult(outNames.nextName())); 413 File f = new File(outNames.currentName()); 414 fileChecker.check(reporter, 415 f, 416 new File(testFileInfo5.goldName + f.getName()), 417 "selectNodeList using 'id(a)' into " + outNames.currentName()); 418 } 419 reporter.testCaseClose(); 420 return true; 421 } 422 423 /** Worker method to return a transformer for serializing. */ getSerializer()424 protected Transformer getSerializer() throws TransformerException 425 { 426 // Set up an identity transformer to use as serializer. 427 Transformer serializer = TransformerFactory.newInstance().newTransformer(); 428 serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 429 return serializer; 430 } 431 432 /** Worker method to parse file into a DOM. */ parseToDOM(String filename)433 protected Document parseToDOM(String filename) throws Exception 434 { 435 reporter.logInfoMsg("Parsing input file "+filename); 436 437 // Set up a DOM tree to query. 438 // Android-added: Look up the file in the java resources. 439 // InputSource in = new InputSource(new FileInputStream(filename)); 440 InputSource in = new InputSource(AndroidFileUtils.getInputFileUrl(filename).openStream()); 441 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 442 Document doc = dfactory.newDocumentBuilder().parse(in); 443 return doc; 444 } 445 446 //----------------------------------------------------------- 447 //---- Basic XSLProcessorTestBase utility methods 448 //----------------------------------------------------------- 449 /** 450 * Convenience method to print out usage information - update if needed. 451 * @return String denoting usage of this test class 452 */ usage()453 public String usage() 454 { 455 return ("Common [optional] options supported by TestXPathAPI:\n" 456 + "(Note: assumes inputDir=.\\tests\\api)\n" 457 + super.usage()); // Grab our parent classes usage as well 458 } 459 460 461 /** Main method to run from the command line. */ main(String[] args)462 public static void main (String[] args) 463 { 464 TestXPathAPI app = new TestXPathAPI(); 465 app.doMain(args); 466 } 467 468 // Android-added: Run main method as a JUnit test case. 469 @FlakyTest(bugId = 292520220) 470 @Test main()471 public void main() { 472 main(new String[0]); 473 } 474 } // end of class ApplyXPath 475 476