1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package javax.xml.xpath.ptests;
  25 
  26 import java.io.FilePermission;
  27 import java.io.IOException;
  28 import java.io.InputStream;
  29 import java.nio.file.Files;
  30 import java.nio.file.Path;
  31 import java.nio.file.Paths;
  32 import javax.xml.XMLConstants;
  33 import javax.xml.namespace.QName;
  34 import javax.xml.parsers.DocumentBuilderFactory;
  35 import javax.xml.parsers.ParserConfigurationException;
  36 import javax.xml.xpath.XPath;
  37 import static javax.xml.xpath.XPathConstants.BOOLEAN;
  38 import static javax.xml.xpath.XPathConstants.NODE;
  39 import static javax.xml.xpath.XPathConstants.NODESET;
  40 import static javax.xml.xpath.XPathConstants.NUMBER;
  41 import static javax.xml.xpath.XPathConstants.STRING;
  42 import javax.xml.xpath.XPathExpressionException;
  43 import javax.xml.xpath.XPathFactory;
  44 import static javax.xml.xpath.ptests.XPathTestConst.XML_DIR;
  45 import jaxp.library.JAXPBaseTest;
  46 import static org.testng.Assert.assertEquals;
  47 import org.testng.annotations.AfterGroups;
  48 import org.testng.annotations.BeforeGroups;
  49 import org.testng.annotations.BeforeTest;
  50 import org.testng.annotations.Test;
  51 import org.w3c.dom.Attr;
  52 import org.w3c.dom.Document;
  53 import org.w3c.dom.NodeList;
  54 import org.xml.sax.InputSource;
  55 import org.xml.sax.SAXException;
  56 
  57 /**
  58  * Class containing the test cases for XPathExpression API.
  59  */
  60 public class XPathExpressionTest extends JAXPBaseTest {
  61     /**
  62      * Document object for testing XML file.
  63      */
  64     private Document document;
  65 
  66     /**
  67      * A XPath for evaluation environment and expressions.
  68      */
  69     private XPath xpath;
  70 
  71     /**
  72      * A QName using default name space.
  73      */
  74     private static final QName TEST_QNAME = new QName(XMLConstants.XML_NS_URI, "");
  75 
  76     /**
  77      * XML File Path.
  78      */
  79     private static final Path XML_PATH = Paths.get(XML_DIR + "widgets.xml");
  80 
  81     /**
  82      * An expression name which locate at "/widgets/widget[@name='a']/@quantity"
  83      */
  84     private static final String EXPRESSION_NAME_A = "/widgets/widget[@name='a']/@quantity";
  85 
  86     /**
  87      * An expression name which locate at "/widgets/widget[@name='b']/@quantity"
  88      */
  89     private static final String EXPRESSION_NAME_B = "/widgets/widget[@name='b']/@quantity";
  90 
  91     /**
  92      * Create Document object and XPath object for every time
  93      * @throws ParserConfigurationException If the factory class cannot be
  94      *                                      loaded, instantiated
  95      * @throws SAXException If any parse errors occur.
  96      * @throws IOException If operation on xml file failed.
  97      */
  98     @BeforeTest
  99     public void setup() throws ParserConfigurationException, SAXException, IOException {
 100         setPermissions(new FilePermission(XML_PATH.toFile().toString(), "read"));
 101         document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(XML_PATH.toFile());
 102         xpath = XPathFactory.newInstance().newXPath();
 103     }
 104 
 105     /**
 106      * Test for evaluate(java.lang.Object item,QName returnType)throws
 107      * XPathExpressionException.
 108      * 
 109      * @throws XPathExpressionException If the expression cannot be evaluated.
 110      */
 111     @Test
 112     public void testCheckXPathExpression01() throws XPathExpressionException {
 113         assertEquals(xpath.compile(EXPRESSION_NAME_A).
 114                 evaluate(document, STRING), "6");
 115     }
 116 
 117     /**
 118      * evaluate(java.lang.Object item,QName returnType) throws NPE if input
 119      * source is null.
 120      * 
 121      * @throws XPathExpressionException If the expression cannot be evaluated.
 122      */
 123     @Test(expectedExceptions = NullPointerException.class)
 124     public void testCheckXPathExpression02() throws XPathExpressionException {
 125         xpath.compile(EXPRESSION_NAME_A).evaluate(null, STRING);
 126     }
 127 
 128     /**
 129      * evaluate(java.lang.Object item,QName returnType) throws NPE if returnType
 130      * is null.
 131      * 
 132      * @throws XPathExpressionException If the expression cannot be evaluated.
 133      */
 134     @Test(expectedExceptions = NullPointerException.class)
 135     public void testCheckXPathExpression03() throws XPathExpressionException {
 136         xpath.compile(EXPRESSION_NAME_A).evaluate(document, null);
 137     }
 138 
 139     /**
 140      * Test for method evaluate(java.lang.Object item,QName returnType).If a
 141      * request is made to evaluate the expression in the absence of a context
 142      * item, simple expressions, such as "1+1", can be evaluated.
 143      * 
 144      * @throws XPathExpressionException If the expression cannot be evaluated.
 145      */
 146     @Test
 147     public void testCheckXPathExpression04() throws XPathExpressionException {
 148         assertEquals(xpath.compile("1+1").evaluate(document, STRING), "2");
 149     }
 150 
 151     /**
 152      * evaluate(java.lang.Object item,QName returnType) throws IAE If returnType
 153      * is not one of the types defined in XPathConstants.
 154      * 
 155      * @throws XPathExpressionException If the expression cannot be evaluated.
 156      */
 157     @Test(expectedExceptions = IllegalArgumentException.class)
 158     public void testCheckXPathExpression05() throws XPathExpressionException {
 159         xpath.compile(EXPRESSION_NAME_A).evaluate(document, TEST_QNAME);
 160     }
 161 
 162     /**
 163      * evaluate(java.lang.Object item,QName returnType) return correct boolean
 164      * value if returnType is Boolean.
 165      * 
 166      * @throws XPathExpressionException If the expression cannot be evaluated.
 167      */
 168     @Test
 169     public void testCheckXPathExpression06() throws XPathExpressionException {
 170         assertEquals(xpath.compile(EXPRESSION_NAME_A).
 171                 evaluate(document, BOOLEAN), true);
 172     }
 173 
 174     /**
 175      * evaluate(java.lang.Object item,QName returnType) return correct boolean
 176      * value if returnType is Boolean.
 177      * 
 178      * @throws XPathExpressionException If the expression cannot be evaluated.
 179      */
 180     @Test
 181     public void testCheckXPathExpression07() throws XPathExpressionException {
 182         assertEquals(xpath.compile(EXPRESSION_NAME_B).
 183             evaluate(document, BOOLEAN), false);
 184     }
 185 
 186     /**
 187      * evaluate(java.lang.Object item,QName returnType) return correct number
 188      * value when return type is Double.
 189      * 
 190      * @throws XPathExpressionException If the expression cannot be evaluated.
 191      */
 192     @Test
 193     public void testCheckXPathExpression08() throws XPathExpressionException {
 194         assertEquals(xpath.compile(EXPRESSION_NAME_A).
 195             evaluate(document, NUMBER), 6d);
 196     }
 197 
 198     /**
 199      * evaluate(java.lang.Object item,QName returnType) evaluate an attribute
 200      * value which returnType is Node.
 201      * 
 202      * @throws XPathExpressionException If the expression cannot be evaluated.
 203      */
 204     @Test
 205     public void testCheckXPathExpression09() throws XPathExpressionException {
 206         Attr attr = (Attr) xpath.compile(EXPRESSION_NAME_A).
 207                 evaluate(document, NODE);
 208         assertEquals(attr.getValue(), "6");
 209     }
 210 
 211     /**
 212      * evaluate(java.lang.Object item,QName returnType) evaluate an attribute
 213      * value which returnType is NodeList.
 214      * 
 215      * @throws XPathExpressionException If the expression cannot be evaluated.
 216      */
 217     @Test
 218     public void testCheckXPathExpression10() throws XPathExpressionException {
 219         NodeList nodeList = (NodeList) xpath.compile(EXPRESSION_NAME_A).
 220                 evaluate(document, NODESET);
 221         Attr attr = (Attr) nodeList.item(0);
 222         assertEquals(attr.getValue(), "6");
 223     }
 224 
 225     /**
 226      * Test for evaluate(java.lang.Object item) when returnType is left off of
 227      * the XPath.evaluate method, all expressions are evaluated to a String
 228      * value.
 229      * 
 230      * @throws XPathExpressionException If the expression cannot be evaluated.
 231      */
 232     @Test
 233     public void testCheckXPathExpression11() throws XPathExpressionException {
 234         assertEquals(xpath.compile(EXPRESSION_NAME_A).evaluate(document), "6");
 235     }
 236 
 237     /**
 238      * evaluate(java.lang.Object item) throws NPE if expression is null.
 239      * 
 240      * @throws XPathExpressionException If the expression cannot be evaluated.
 241      */
 242     @Test(expectedExceptions = NullPointerException.class)
 243     public void testCheckXPathExpression12() throws XPathExpressionException {
 244         xpath.compile(null).evaluate(document);
 245     }
 246 
 247     /**
 248      * evaluate(java.lang.Object item) when a request is made to evaluate the
 249      * expression in the absence of a context item, simple expressions, such as
 250      * "1+1", can be evaluated.
 251      * 
 252      * @throws XPathExpressionException If the expression cannot be evaluated.
 253      */
 254     @Test
 255     public void testCheckXPathExpression13() throws XPathExpressionException {
 256         assertEquals(xpath.compile("1+1").evaluate(document), "2");
 257     }
 258 
 259     /**
 260      * evaluate(java.lang.Object item) throws NPE if document is null.
 261      * 
 262      * @throws XPathExpressionException If the expression cannot be evaluated.
 263      */
 264     @Test(expectedExceptions = NullPointerException.class)
 265     public void testCheckXPathExpression14() throws XPathExpressionException {
 266         xpath.compile(EXPRESSION_NAME_A).evaluate(null);
 267     }
 268 
 269    
 270     /**
 271      * Save system property for restoring.
 272      */
 273     @BeforeGroups (groups = {"readLocalFiles"})
 274     public void setFilePermissions() {
 275         setPermissions(new FilePermission(XML_DIR + "/-",
 276                 "read"));
 277     }
 278     
 279     /**
 280      * Restore the system property.
 281      */
 282     @AfterGroups (groups = {"readLocalFiles"})
 283     public void restoreFilePermissions() {
 284         setPermissions();
 285     }
 286 
 287     /**
 288      * valuate(InputSource source) return a string value if return type is
 289      * String.
 290      * 
 291      * @throws XPathExpressionException If the expression cannot be evaluated.
 292      * @throws IOException if the file exists but is a directory rather than
 293      *         a regular file, does not exist but cannot be created, or cannot 
 294      *         be opened for any other reason.
 295      */
 296     @Test (groups = {"readLocalFiles"})
 297     public void testCheckXPathExpression15() throws XPathExpressionException, 
 298             IOException {
 299         try (InputStream is = Files.newInputStream(XML_PATH)) {
 300             assertEquals(xpath.compile(EXPRESSION_NAME_A).
 301                     evaluate(new InputSource(is)), "6");
 302         }
 303     }
 304 
 305     /**
 306      * evaluate(InputSource source) throws NPE if input source is null.
 307      * 
 308      * @throws XPathExpressionException If the expression cannot be evaluated.
 309      */
 310     @Test(expectedExceptions = NullPointerException.class)
 311     public void testCheckXPathExpression16() throws XPathExpressionException {
 312         xpath.compile(EXPRESSION_NAME_A).evaluate(null);
 313     }
 314 
 315     /**
 316      * evaluate(InputSource source) throws NPE if expression is null.
 317      * 
 318      * @throws XPathExpressionException If the expression cannot be evaluated.
 319      * @throws IOException if the file exists but is a directory rather than
 320      *         a regular file, does not exist but cannot be created, or cannot 
 321      *         be opened for any other reason.
 322      */
 323     @Test(groups = {"readLocalFiles"}, expectedExceptions = NullPointerException.class)
 324     public void testCheckXPathExpression17() throws IOException, 
 325             XPathExpressionException {
 326         try (InputStream is = Files.newInputStream(XML_PATH)) {
 327             xpath.compile(null).evaluate(new InputSource(is));
 328         }
 329     }
 330 
 331     /**
 332      * evaluate(InputSource source) throws XPathExpressionException if
 333      * returnType is String junk characters.
 334      * 
 335      * @throws XPathExpressionException If the expression cannot be evaluated.
 336      * @throws IOException if the file exists but is a directory rather than
 337      *         a regular file, does not exist but cannot be created, or cannot 
 338      *         be opened for any other reason.
 339      */
 340     @Test(groups = {"readLocalFiles"}, expectedExceptions = XPathExpressionException.class)
 341     public void testCheckXPathExpression18() throws XPathExpressionException, 
 342             IOException {
 343         try (InputStream is = Files.newInputStream(XML_PATH)) {
 344             xpath.compile("-*&").evaluate(new InputSource(is));
 345         }
 346     }
 347 
 348     /**
 349      * evaluate(InputSource source) throws XPathExpressionException if
 350      * expression is a blank string " ".
 351      * 
 352      * @throws XPathExpressionException If the expression cannot be evaluated.
 353      * @throws IOException if the file exists but is a directory rather than
 354      *         a regular file, does not exist but cannot be created, or cannot 
 355      *         be opened for any other reason.
 356      */
 357     @Test(groups = {"readLocalFiles"}, expectedExceptions = XPathExpressionException.class)
 358     public void testCheckXPathExpression19() throws XPathExpressionException,
 359             IOException {
 360         try (InputStream is = Files.newInputStream(XML_PATH)) {
 361             xpath.compile(" ").evaluate(new InputSource(is));
 362         }
 363     }
 364 
 365     /**
 366      * Test for evaluate(InputSource source,QName returnType) returns a string
 367      * value if returnType is String.
 368      * 
 369      * @throws XPathExpressionException If the expression cannot be evaluated.
 370      * @throws IOException if the file exists but is a directory rather than
 371      *         a regular file, does not exist but cannot be created, or cannot 
 372      *         be opened for any other reason.
 373      */
 374     @Test(groups = {"readLocalFiles"})
 375     public void testCheckXPathExpression20() throws IOException, 
 376             XPathExpressionException {
 377         try (InputStream is = Files.newInputStream(XML_PATH)) {
 378             assertEquals(xpath.compile(EXPRESSION_NAME_A).
 379                 evaluate(new InputSource(is), STRING), "6");
 380         }
 381     }
 382 
 383     /**
 384      * evaluate(InputSource source,QName returnType) throws NPE if source is
 385      * null.
 386      * 
 387      * @throws XPathExpressionException If the expression cannot be evaluated.
 388      */
 389     @Test(expectedExceptions = NullPointerException.class)
 390     public void testCheckXPathExpression21() throws XPathExpressionException {
 391         xpath.compile(EXPRESSION_NAME_A).evaluate(null, STRING);
 392     }
 393 
 394     /**
 395      * evaluate(InputSource source,QName returnType) throws NPE if expression is
 396      * null.
 397      * 
 398      * @throws XPathExpressionException If the expression cannot be evaluated.
 399      * @throws IOException if the file exists but is a directory rather than
 400      *         a regular file, does not exist but cannot be created, or cannot 
 401      *         be opened for any other reason.
 402      */
 403     @Test(groups = {"readLocalFiles"}, expectedExceptions = NullPointerException.class)
 404     public void testCheckXPathExpression22() throws IOException, 
 405             XPathExpressionException {
 406         try (InputStream is = Files.newInputStream(XML_PATH)) {
 407             xpath.compile(null).evaluate(new InputSource(is), STRING);
 408         }
 409     }
 410 
 411     /**
 412      * evaluate(InputSource source,QName returnType) throws NPE if returnType is
 413      * null.
 414      * 
 415      * @throws XPathExpressionException If the expression cannot be evaluated.
 416      * @throws IOException if the file exists but is a directory rather than
 417      *         a regular file, does not exist but cannot be created, or cannot 
 418      *         be opened for any other reason.
 419      */
 420     @Test(groups = {"readLocalFiles"}, expectedExceptions = NullPointerException.class)
 421     public void testCheckXPathExpression23() throws IOException,
 422             XPathExpressionException {
 423         try (InputStream is = Files.newInputStream(XML_PATH)) {
 424             xpath.compile(EXPRESSION_NAME_A).evaluate(new InputSource(is), null);
 425         }
 426     }
 427 
 428     /**
 429      * evaluate(InputSource source,QName returnType) throws
 430      * XPathExpressionException if expression is junk characters.
 431      * 
 432      * @throws XPathExpressionException If the expression cannot be evaluated.
 433      * @throws IOException if the file exists but is a directory rather than
 434      *         a regular file, does not exist but cannot be created, or cannot 
 435      *         be opened for any other reason.
 436      */
 437     @Test(groups = {"readLocalFiles"}, expectedExceptions = XPathExpressionException.class)
 438     public void testCheckXPathExpression24() throws XPathExpressionException,
 439             IOException {
 440         try (InputStream is = Files.newInputStream(XML_PATH)) {
 441             xpath.compile("-*&").evaluate(new InputSource(is), STRING);
 442         }
 443     }
 444 
 445     /**
 446      * evaluate(InputSource source,QName returnType) throws
 447      * XPathExpressionException if expression is blank " ".
 448      * 
 449      * @throws XPathExpressionException If the expression cannot be evaluated.
 450      * @throws IOException if the file exists but is a directory rather than
 451      *         a regular file, does not exist but cannot be created, or cannot 
 452      *         be opened for any other reason.
 453      */
 454     @Test(groups = {"readLocalFiles"}, expectedExceptions = XPathExpressionException.class)
 455     public void testCheckXPathExpression25() throws XPathExpressionException, 
 456             IOException {
 457         try (InputStream is = Files.newInputStream(XML_PATH)) {
 458             xpath.compile(" ").evaluate(new InputSource(is), STRING);
 459         }
 460     }
 461 
 462     /**
 463      * evaluate(InputSource source,QName returnType) throws
 464      * IllegalArgumentException if returnType is not one of the types defined
 465      * in XPathConstants.
 466      * 
 467      * @throws XPathExpressionException If the expression cannot be evaluated.
 468      * @throws IOException if the file exists but is a directory rather than
 469      *         a regular file, does not exist but cannot be created, or cannot 
 470      *         be opened for any other reason.
 471      */
 472     @Test(groups = {"readLocalFiles"}, expectedExceptions = IllegalArgumentException.class)
 473     public void testCheckXPathExpression26() throws IOException, 
 474             XPathExpressionException {
 475         try (InputStream is = Files.newInputStream(XML_PATH)) {
 476             xpath.compile(EXPRESSION_NAME_A).evaluate(new InputSource(is), TEST_QNAME);
 477         }
 478     }
 479 
 480     /**
 481      * evaluate(InputSource source,QName returnType) return a correct boolean
 482      * value if returnType is Boolean.
 483      * 
 484      * @throws XPathExpressionException If the expression cannot be evaluated.
 485      * @throws IOException if the file exists but is a directory rather than
 486      *         a regular file, does not exist but cannot be created, or cannot 
 487      *         be opened for any other reason.
 488      */
 489     @Test(groups = {"readLocalFiles"})
 490     public void testCheckXPathExpression27() throws IOException,
 491             XPathExpressionException {
 492         try (InputStream is = Files.newInputStream(XML_PATH)) {
 493             assertEquals(xpath.compile(EXPRESSION_NAME_A).
 494                 evaluate(new InputSource(is), BOOLEAN), true);
 495         }
 496     }
 497 
 498     /**
 499      * evaluate(InputSource source,QName returnType) return a correct boolean
 500      * value if returnType is Boolean.
 501      * 
 502      * @throws XPathExpressionException If the expression cannot be evaluated.
 503      * @throws IOException if the file exists but is a directory rather than
 504      *         a regular file, does not exist but cannot be created, or cannot 
 505      *         be opened for any other reason.
 506      */
 507     @Test(groups = {"readLocalFiles"})
 508     public void testCheckXPathExpression28() throws IOException,
 509             XPathExpressionException {
 510         try (InputStream is = Files.newInputStream(XML_PATH)) {
 511             assertEquals(xpath.compile(EXPRESSION_NAME_B).
 512                 evaluate(new InputSource(is), BOOLEAN), false);
 513         }
 514     }
 515 
 516     /**
 517      * evaluate(InputSource source,QName returnType) return a correct number
 518      * value if returnType is Number.
 519      * 
 520      * @throws XPathExpressionException If the expression cannot be evaluated.
 521      * @throws IOException if the file exists but is a directory rather than
 522      *         a regular file, does not exist but cannot be created, or cannot 
 523      *         be opened for any other reason.
 524      */
 525     @Test(groups = {"readLocalFiles"})
 526     public void testCheckXPathExpression29() throws IOException, 
 527             XPathExpressionException {
 528         try (InputStream is = Files.newInputStream(XML_PATH)) {
 529             assertEquals(xpath.compile(EXPRESSION_NAME_A).
 530                 evaluate(new InputSource(is), NUMBER), 6d);
 531         }
 532     }
 533 
 534     /**
 535      * Test for evaluate(InputSource source,QName returnType) returns a node if
 536      * returnType is Node.
 537      * 
 538      * @throws XPathExpressionException If the expression cannot be evaluated.
 539      * @throws IOException if the file exists but is a directory rather than
 540      *         a regular file, does not exist but cannot be created, or cannot 
 541      *         be opened for any other reason.
 542      */
 543     @Test(groups = {"readLocalFiles"})
 544     public void testCheckXPathExpression30() throws IOException, 
 545             XPathExpressionException {
 546         try (InputStream is = Files.newInputStream(XML_PATH)) {
 547             Attr attr = (Attr) xpath.compile(EXPRESSION_NAME_A).
 548                 evaluate(new InputSource(is), NODE);
 549             assertEquals(attr.getValue(), "6");
 550         }
 551     }
 552 
 553     /**
 554      * Test for evaluate(InputSource source,QName returnType) return a node list
 555      * if returnType is NodeList.
 556      * 
 557      * @throws XPathExpressionException If the expression cannot be evaluated.
 558      * @throws IOException if the file exists but is a directory rather than
 559      *         a regular file, does not exist but cannot be created, or cannot 
 560      *         be opened for any other reason.
 561      */
 562     @Test(groups = {"readLocalFiles"})
 563     public void testCheckXPathExpression31() throws IOException, 
 564             XPathExpressionException {
 565         try (InputStream is = Files.newInputStream(XML_PATH)) {
 566             NodeList nodeList = (NodeList) xpath.compile(EXPRESSION_NAME_A).
 567                 evaluate(new InputSource(is), NODESET);
 568             assertEquals(((Attr) nodeList.item(0)).getValue(), "6");
 569         }
 570     }
 571 }