Skip to content

Commit

Permalink
8290836: Improve test coverage for XPath functions: String Functions
Browse files Browse the repository at this point in the history
8290837: Improve test coverage for XPath functions: Boolean Functions
8290838: Improve test coverage for XPath functions: Number Functions

Backport-of: d889264c6123b6c28bdd6336f5ae547e4e441aa7
  • Loading branch information
Victor Rudometov authored and Paul Hohensee committed Feb 3, 2023
1 parent fe770e3 commit 2fa09bb
Show file tree
Hide file tree
Showing 5 changed files with 818 additions and 15 deletions.
141 changes: 141 additions & 0 deletions test/jaxp/javax/xml/jaxp/unittest/xpath/XPathBooleanFnTest.java
@@ -0,0 +1,141 @@
/*
* 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 javax.xml.xpath.XPathExpressionException;

/*
* @test
* @bug 8290837
* @library /javax/xml/jaxp/unittest
* @run testng xpath.XPathBooleanFnTest
* @summary Tests the XPath Boolean Functions
*/
public class XPathBooleanFnTest extends XPathTestBase {

private static final Document doc = getDtdDocument();

/*
* DataProvider for testing the boolean, not, true, false and lang
* functions.
* Data columns:
* see parameters of the test "testBooleanFn"
*/
@DataProvider(name = "booleanExpTestCases")
public Object[][] getBooleanExp() {
return new Object[][]{
{"true()", true},
{"false()", false},

{"boolean(true())", true},
{"boolean(false())", false},
{"boolean(1)", true},
{"boolean(0)", false},
{"boolean(-1)", true},
{"boolean(1+1)", true},
{"boolean(1-1)", false},
{"boolean(1+'abc')", false},
{"boolean('abc')", true},
{"boolean('')", false},
{"boolean(//Name)", true},
{"boolean(//LastName)", false},
{"boolean(//Customer[1]/ClubMember)", true},
{"boolean(//Customer[2]/ClubMember)", true},
{"boolean(//Customer[2]/ClubMember='true')", false},
{"boolean(//Customer[1]/ClubMember or " +
"//Customer[2]/ClubMember)", true},
{"boolean(//Customer[1]/ClubMember and " +
"//Customer[2]/ClubMember)", true},
{"boolean(//*[boolean(.)=true()])", true},
{"boolean(//*[boolean(.)=false()])", false},

{"not(1)", false},
{"not(-1)", false},
{"not(0)", true},
{"not(true())", false},
{"not(false())", true},
{"not(//Customer[1]/ClubMember)", false},
{"not(//Customer[2]/ClubMember)", false},
{"not(//Customer[2]/ClubMember='true')", true},
{"boolean(//*[not(.)=true()])", false},
{"boolean(//*[not(.)=false()])", true},

{"boolean(//*[lang('en')])", true},
{"boolean(//*[lang('es')])", false},
};
}

/*
* DataProvider for testing XPathExpressionException being thrown on
* invalid boolean function usage.
* Data columns:
* see parameters of the test "testExceptionOnEval"
*/
@DataProvider(name = "exceptionExpTestCases")
public Object[][] getExceptionExp() {
return new Object[][]{
// Argument is required for these functions
{"boolean()"},
{"//*[boolean()=true()]"},
{"not()"},
{"//*[not()=true()]"},
{"lang()"},
{"/*[lang()=true()]"},

// No arguments should be passed to these functions
{"true(1)"},
{"false(0)"},
{"//*[true(.)=true()]"},
{"//*[false(.)=false()]"},
};
}

/**
* Verifies that the result of evaluating the boolean, not, true, false
* and lang functions matches the expected result.
*
* @param exp XPath expression
* @param expected expected result
* @throws Exception if test fails
*/
@Test(dataProvider = "booleanExpTestCases")
void testBooleanFn(String exp, boolean expected) throws Exception {
testExp(doc, exp, expected, Boolean.class);
}

/**
* Verifies that XPathExpressionException is thrown on xpath evaluation.
*
* @param exp XPath expression
*/
@Test(dataProvider = "exceptionExpTestCases")
void testExceptionOnEval(String exp) {
Assert.assertThrows(XPathExpressionException.class, () -> testEval(doc,
exp));
}
}
76 changes: 69 additions & 7 deletions test/jaxp/javax/xml/jaxp/unittest/xpath/XPathNodeSetFnTest.java
Expand Up @@ -69,29 +69,35 @@ public Object[][] getCountExp() {
{"count(//Customer)", CUSTOMERS},
{"count(//@id)", ID_ATTRIBUTES},
{"count(//Customer/@id)", CUSTOMERS},
{"count(//@*)", ID_ATTRIBUTES + FOO_ID_ATTRIBUTES},
{"count(//@*)",
LANG_ATTRIBUTES + ID_ATTRIBUTES + FOO_ID_ATTRIBUTES},
{"count(//*)",
ROOT + CUSTOMERS + FOO_CUSTOMERS +
(CUSTOMERS + FOO_CUSTOMERS) *
CUSTOMER_ELEMENTS},
(CUSTOMER_ELEMENTS + ADDRESS_ELEMENTS)},
{"count(//*[@id])", ID_ATTRIBUTES},
{"count(./*)", ROOT},
{"count(.)", ROOT},
{"count(//Customer[1]/following::*)",
CUSTOMERS - 1 + FOO_CUSTOMERS +
(CUSTOMERS - 1 + FOO_CUSTOMERS) *
CUSTOMER_ELEMENTS},
(CUSTOMER_ELEMENTS + ADDRESS_ELEMENTS)},
{"count(//Customer[1]/following-sibling::*)",
CUSTOMERS - 1 + FOO_CUSTOMERS},
{"count(//Customer[3]/preceding::*)",
CUSTOMERS - 1 + (CUSTOMERS - 1) * CUSTOMER_ELEMENTS},
CUSTOMERS - 1 + (CUSTOMERS - 1) *
(CUSTOMER_ELEMENTS + ADDRESS_ELEMENTS)},
{"count(//Customer[3]/preceding-sibling::*)", CUSTOMERS - 1},
{"count(//Customer[1]/ancestor::*)", ROOT},
{"count(//Customer[1]/ancestor-or-self::*)", ROOT + 1},
{"count(//Customer[1]/descendant::*)", CUSTOMER_ELEMENTS},
{"count(//Customer[1]/descendant::*)",
CUSTOMER_ELEMENTS + ADDRESS_ELEMENTS},
{"count(//Customer[1]/descendant-or-self::*)",
CUSTOMER_ELEMENTS + 1},
CUSTOMER_ELEMENTS + ADDRESS_ELEMENTS + 1},
// node() returns all children of the context node including
// element nodes and text nodes.
{"count(//Customer/node())",
ID_ATTRIBUTES + CUSTOMERS * CUSTOMER_ELEMENTS},
CUSTOMERS + CUSTOMERS * (CUSTOMER_ELEMENTS * 2)},
};
}

Expand All @@ -104,6 +110,7 @@ public Object[][] getCountExp() {
public Object[][] getPositionExp() {
return new Object[][]{
{"//Customer[position()=1]", "Customer_x1"},
{"//Customer[position()]", "Customer_x1"},
{"//Customer[position()=last()]", "Customer_x3"},
{"//Customer[position()>1 and position()<last()]",
"Customer_x2"},
Expand All @@ -125,18 +132,62 @@ public Object[][] getNameExp() {
{"local-name(//Customer/@id)", "id"},
{"local-name(//foo:Customer/@foo:id)", "id"},
{"local-name(//*[local-name()='Customer'])", "Customer"},
{"local-name(//*[local-name(.)='Customer'])", "Customer"},
{"namespace-uri(.)", ""},
{"namespace-uri(//Customers)", ""},
{"namespace-uri(//Customer)", ""},
{"namespace-uri(//foo:Customer)", "foo"},
{"namespace-uri(//@id)", ""},
{"namespace-uri(//@foo:id)", "foo"},
{"name(//*[namespace-uri()=\"foo\"])", "foo:Customer"},
{"name(//*[namespace-uri(.)=\"foo\"])", "foo:Customer"},
{"name(//Customer)", "Customer"},
{"name(//foo:Customer)", "foo:Customer"},
{"name(//Customer/@id)", "id"},
{"name(//foo:Customer/@foo:id)", "foo:id"},
{"name(//*[name()='foo:Customer'])", "foo:Customer"},
{"name(//*[name(.)='foo:Customer'])", "foo:Customer"},
};
}

/*
* DataProvider for testing XPathExpressionException being thrown on
* invalid node set function usage.
* Data columns:
* see parameters of the test "testExceptionOnEval"
*/
@DataProvider(name = "exceptionExpTestCases")
public Object[][] getExceptionExp() {
return new Object[][]{
// Argument is required for these functions
{"//Customer[id()]"},
{"//Customer[id()='x1']"},
{"//Customer[count()]"},
{"//*[count()=3]"},

// No argument should be passed to these functions
{"//Customer[position(.)]"},
{"//*[position(//Customer[1])]"},
{"//Customer[last(.)]"},
{"//*[last(//Customer[1])]"},

// Node-set argument is required for these functions
{"count(1)"},
{"count(true())"},
{"count('')"},
{"count('abc')"},
{"local-name(1)"},
{"local-name(true())"},
{"local-name('')"},
{"local-name('abc')"},
{"name(1)"},
{"name(true())"},
{"name('')"},
{"name('abc')"},
{"namespace-uri(1)"},
{"namespace-uri(true())"},
{"namespace-uri('')"},
{"namespace-uri('abc')"},
};
}

Expand Down Expand Up @@ -219,4 +270,15 @@ void testNameFn(String exp, String expected) throws Exception {
Assert.assertEquals(s, expected);
Assert.assertEquals(s2, s);
}

/**
* Verifies that XPathExpressionException is thrown on xpath evaluation.
*
* @param exp XPath expression
*/
@Test(dataProvider = "exceptionExpTestCases")
void testExceptionOnEval(String exp) {
Assert.assertThrows(XPathExpressionException.class, () -> testEval(doc,
exp));
}
}

1 comment on commit 2fa09bb

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.