8289508: Improve test coverage for XPath Axes: ancestor, ancestor-or-self, preceding, and preceding-sibling
Reviewed-by: joehw
This commit is contained in:
parent
cb5771dc2a
commit
caae53f4da
186
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathAncestorsTest.java
Normal file
186
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathAncestorsTest.java
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package xpath;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8289508
|
||||||
|
* @library /javax/xml/jaxp/unittest
|
||||||
|
* @run testng/othervm xpath.XPathAncestorsTest
|
||||||
|
* @summary Tests for XPath ancestor and ancestor-or-self axis specifiers.
|
||||||
|
*/
|
||||||
|
public class XPathAncestorsTest {
|
||||||
|
|
||||||
|
private static final String XML = """
|
||||||
|
<store>
|
||||||
|
<book id="1" lang="en">
|
||||||
|
<title/>
|
||||||
|
<author id="1"/>
|
||||||
|
<isbn>1234</isbn>
|
||||||
|
</book>
|
||||||
|
<book id="2" lang="en">
|
||||||
|
<title/>
|
||||||
|
<author id="2"/>
|
||||||
|
<isbn>5678</isbn>
|
||||||
|
</book>
|
||||||
|
</store>
|
||||||
|
""";
|
||||||
|
private static final Document doc;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
var builder =
|
||||||
|
DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
InputStream s = new ByteArrayInputStream(XML.getBytes());
|
||||||
|
doc = builder.parse(s);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Exception while initializing XML document");
|
||||||
|
throw new RuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataProvider:provides XPath expression using ancestor/ancestor-or-self
|
||||||
|
* and the expected node(s) from the expression
|
||||||
|
*/
|
||||||
|
@DataProvider(name = "ancestors_axes")
|
||||||
|
public Object[][] getXPathAncestors() {
|
||||||
|
return new Object[][]{
|
||||||
|
//test ancestor
|
||||||
|
|
||||||
|
// abbreviated text
|
||||||
|
{"//author/ancestor::book/ancestor::store", "/store"},
|
||||||
|
{"//isbn/ancestor::store", "/store"},
|
||||||
|
{"//ancestor::book[1]", "//book[1]"},
|
||||||
|
|
||||||
|
// any node
|
||||||
|
{"//book/ancestor::*", "/store"},
|
||||||
|
{"//author/ancestor::*[ancestor::store]/ancestor::store", "/store"},
|
||||||
|
{"//author/ancestor::node()[ancestor::store]", "//book"},
|
||||||
|
|
||||||
|
// dot reference
|
||||||
|
{"//author/ancestor::book/..", "/store"},
|
||||||
|
{"//author/ancestor::*[ancestor::store]/..", "/store"},
|
||||||
|
{"//ancestor::book/..", "/store"},
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
{"//author/ancestor::*[@id]/parent::*", "/store"},
|
||||||
|
{"//author/parent::*[@id]/ancestor::*", "/store"},
|
||||||
|
{"//author[@id='1']/ancestor::book[1]", "//book[1]"},
|
||||||
|
{"//author[@*]/ancestor::book[1]", "//book[1]"},
|
||||||
|
|
||||||
|
//test ancestor-or-self
|
||||||
|
|
||||||
|
// any node, indexing, id
|
||||||
|
{"/store/ancestor-or-self::*", "/store"},
|
||||||
|
{"//book[*]/ancestor-or-self::book[1]", "//book[1]"},
|
||||||
|
{"/store/book[@*]/ancestor-or-self::book[1]", "//book[1]"},
|
||||||
|
{"//book[@id='1']/ancestor-or-self::book[1]", "//book[1]"},
|
||||||
|
{"//author[@id='2']/ancestor-or-self::book", "//book[2]"},
|
||||||
|
{"//book[1]/ancestor-or-self::store", "/store"},
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataProvider: provides XPath expressions that return empty NodeSet
|
||||||
|
*/
|
||||||
|
@DataProvider(name = "emptyNodeSet")
|
||||||
|
public Object[][] getEmptyNodeSet() {
|
||||||
|
return new Object[][]{
|
||||||
|
// test ancestor
|
||||||
|
|
||||||
|
// abbreviated text
|
||||||
|
{"/store/book/ancestor::book"},
|
||||||
|
{"//author/ancestor::store[2]"},
|
||||||
|
{"//author[3]/ancestor::store"},
|
||||||
|
|
||||||
|
// any nodes
|
||||||
|
{"/store/ancestor::*"},
|
||||||
|
{"/store/book[3]/ancestor::*"},
|
||||||
|
{"//book[*]/../ancestor::*"},
|
||||||
|
{"/store/book[@id='3']/ancestor::*"},
|
||||||
|
{"//book/ssn/ancestor::*"},
|
||||||
|
{"//author/ancestor::*[ancestor::isbn]"},
|
||||||
|
{"/store/../ancestor::*"},
|
||||||
|
{"//ancestor::author"},
|
||||||
|
|
||||||
|
// id
|
||||||
|
{"/store/book[@id='3']/ancestor::*"},
|
||||||
|
{"/store[@*]/ancestor::*"},
|
||||||
|
{"/book[@*]/ancestor::*/ancestor::*"},
|
||||||
|
{"//book[@category]/ancestor::*"},
|
||||||
|
|
||||||
|
//test ancestor-or-self
|
||||||
|
|
||||||
|
// any nodes, id
|
||||||
|
{"/store/../ancestor-or-self::*"},
|
||||||
|
{"//book[3]/ancestor-or-self::*"},
|
||||||
|
{"//author/ancestor-or-self::title"},
|
||||||
|
{"//author[@id='2']/ancestor-or-self::*[@id='1']"},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies XPath ancestor and ancestor-or-self axis specifiers
|
||||||
|
* by comparing expression and expected result.
|
||||||
|
* @param exp XPath expression
|
||||||
|
* @param expected expected result
|
||||||
|
* @throws Exception if test failed
|
||||||
|
*/
|
||||||
|
@Test(dataProvider = "ancestors_axes")
|
||||||
|
void testXPathAncestors(String exp, String parent) throws Exception {
|
||||||
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||||
|
Node result = xPath.evaluateExpression(exp, doc, Node.class);
|
||||||
|
Node expected = xPath.evaluateExpression(parent, doc, Node.class);
|
||||||
|
Assert.assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies no nodes returned from the XPath expression.
|
||||||
|
*
|
||||||
|
* @param exp XPath expression
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test(dataProvider = "emptyNodeSet")
|
||||||
|
void testEmptyNodeSet(String exp) throws Exception {
|
||||||
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||||
|
Node result = xPath.evaluateExpression(exp, doc, Node.class);
|
||||||
|
Assert.assertEquals(result, null);
|
||||||
|
}
|
||||||
|
}
|
185
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathPrecedingTest.java
Normal file
185
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathPrecedingTest.java
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package xpath;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8289508
|
||||||
|
* @library /javax/xml/jaxp/unittest
|
||||||
|
* @run testng/othervm xpath.XPathPrecedingTest
|
||||||
|
* @summary Tests for XPath preceding and preceding-sibling axis specifiers.
|
||||||
|
*/
|
||||||
|
public class XPathPrecedingTest {
|
||||||
|
|
||||||
|
private static final String XML = """
|
||||||
|
<store>
|
||||||
|
<book id="1" lang="en">
|
||||||
|
<title>Book1</title>
|
||||||
|
<author id="1"/>
|
||||||
|
<isbn>1234</isbn>
|
||||||
|
</book>
|
||||||
|
<book id="2" lang="en" xmlns="www.foo.com">
|
||||||
|
<title>Book2</title>
|
||||||
|
<author id="2"/>
|
||||||
|
<isbn>5678</isbn>
|
||||||
|
</book>
|
||||||
|
</store>
|
||||||
|
""";
|
||||||
|
private static final Document doc;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
var builder =
|
||||||
|
DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
InputStream s = new ByteArrayInputStream(XML.getBytes());
|
||||||
|
doc = builder.parse(s);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Exception while initializing XML document");
|
||||||
|
throw new RuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataProvider: provides XPath expression using preceding/preceding-sibling
|
||||||
|
* and the expected node(s) from the expression
|
||||||
|
*/
|
||||||
|
@DataProvider(name = "preceding_axes")
|
||||||
|
public Object[][] getXPathPreceding() {
|
||||||
|
return new Object[][]{
|
||||||
|
// test preceding
|
||||||
|
|
||||||
|
// any nodes
|
||||||
|
{"/store/book[1]/author/preceding::*", "/store/book[1]/title"},
|
||||||
|
|
||||||
|
// abbreviated text
|
||||||
|
{"/store/book[1]/isbn/preceding::*[1]", "/store/book[1]/author"},
|
||||||
|
{"(/store/book[1]/isbn/preceding::*)[1]", "/store/book[1]/title"},
|
||||||
|
{"//isbn/preceding::book", "//book[1]"},
|
||||||
|
{"//book[2]/preceding::book", "//book[1]"},
|
||||||
|
{"/store/book[preceding::book]", "//book[2]"},
|
||||||
|
{"/store/book[preceding::book]/preceding::book", "//book[1]"},
|
||||||
|
|
||||||
|
// id
|
||||||
|
{"//author[@id='2']/../preceding::book", "//book[1]"},
|
||||||
|
{"//author[@id='2']/preceding::node()/preceding::book", "//book[1]"},
|
||||||
|
{"//author[@id='1']/preceding::title", "//book[1]/title"},
|
||||||
|
|
||||||
|
//test preceding-sibling
|
||||||
|
|
||||||
|
// any node
|
||||||
|
{"/store/book[1]/author/preceding-sibling::*", "/store/book[1]/title"},
|
||||||
|
{"/store/book[2]/preceding-sibling::*", "//book[1]"},
|
||||||
|
{"//author/preceding-sibling::*", "//title"},
|
||||||
|
|
||||||
|
// abbreviated text
|
||||||
|
{"/store/book[preceding::book]/preceding-sibling::book", "//book[1]"},
|
||||||
|
|
||||||
|
// id
|
||||||
|
{"/store/book[1]/isbn[preceding-sibling::author[@id='1']]", "/store/book[1]/isbn"},
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataProvider: provides XPath expressions that return empty NodeSet
|
||||||
|
*/
|
||||||
|
@DataProvider(name = "emptyNodeSet")
|
||||||
|
public Object[][] getEmptyNodeSet() {
|
||||||
|
return new Object[][]{
|
||||||
|
//test preceding
|
||||||
|
|
||||||
|
// abbreviated text
|
||||||
|
{"/store/preceding::book"},
|
||||||
|
{"/store/book[1]/author/preceding::author"},
|
||||||
|
|
||||||
|
// any nodes/id
|
||||||
|
{"/store/book[1]/preceding::*"},
|
||||||
|
{"/store/book[1]/title/preceding::*"},
|
||||||
|
{"/store/book[@id='1']/preceding::*"},
|
||||||
|
|
||||||
|
//test preceding-sibling
|
||||||
|
|
||||||
|
// any nodes
|
||||||
|
{"/store/book[1]/preceding-sibling::*"},
|
||||||
|
{"/store/book[2]/title/preceding-sibling::*"},
|
||||||
|
|
||||||
|
// abbreviated text / id
|
||||||
|
{"/store/book[1]/author/preceding-sibling::isbn"},
|
||||||
|
{"//author[@id='2']/preceding-sibling::book"},
|
||||||
|
{"//author[@id='2']/preceding-sibling::node()/preceding-sibling::author"},
|
||||||
|
|
||||||
|
// attribute / namespace
|
||||||
|
{"/store/book[2]/@id/preceding-sibling::*"},
|
||||||
|
{"/store/book/@lang/preceding-sibling::*"},
|
||||||
|
{"/store/book[2]/namespace::*/preceding-sibling::*"},
|
||||||
|
|
||||||
|
// text node
|
||||||
|
{"/store/book[2]/isbn/text()/preceding-sibling::*"},
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies XPath preceding and preceding-sibling axis specifiers by
|
||||||
|
* comparing expression and expected result.
|
||||||
|
* @param exp XPath expression
|
||||||
|
* @param expected expected result
|
||||||
|
* @throws Exception if test failed
|
||||||
|
*/
|
||||||
|
@Test(dataProvider = "preceding_axes")
|
||||||
|
void testXPathPreceding(String exp, String parent) throws Exception {
|
||||||
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||||
|
Node result = xPath.evaluateExpression(exp, doc, Node.class);
|
||||||
|
Node expected = xPath.evaluateExpression(parent, doc, Node.class);
|
||||||
|
Assert.assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies no nodes returned from the XPath expression.
|
||||||
|
*
|
||||||
|
* @param exp XPath expression
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test(dataProvider = "emptyNodeSet")
|
||||||
|
void testEmptyNodeSet(String exp) throws Exception {
|
||||||
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||||
|
Node result = xPath.evaluateExpression(exp, doc, Node.class);
|
||||||
|
Assert.assertEquals(result, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user