mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 09:53:18 +00:00
8290836: Improve test coverage for XPath functions: String Functions
8290837: Improve test coverage for XPath functions: Boolean Functions 8290838: Improve test coverage for XPath functions: Number Functions Reviewed-by: joehw
This commit is contained in:
parent
ae1a9a0b25
commit
d889264c61
141
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathBooleanFnTest.java
Normal file
141
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathBooleanFnTest.java
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
@ -69,29 +69,35 @@ public class XPathNodeSetFnTest extends XPathTestBase {
|
||||
{"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)},
|
||||
};
|
||||
}
|
||||
|
||||
@ -104,6 +110,7 @@ public class XPathNodeSetFnTest extends XPathTestBase {
|
||||
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"},
|
||||
@ -125,6 +132,7 @@ public class XPathNodeSetFnTest extends XPathTestBase {
|
||||
{"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)", ""},
|
||||
@ -132,11 +140,54 @@ public class XPathNodeSetFnTest extends XPathTestBase {
|
||||
{"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')"},
|
||||
};
|
||||
}
|
||||
|
||||
@ -219,4 +270,15 @@ public class XPathNodeSetFnTest extends XPathTestBase {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
162
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathNumberFnTest.java
Normal file
162
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathNumberFnTest.java
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290838
|
||||
* @library /javax/xml/jaxp/unittest
|
||||
* @run testng xpath.XPathNumberFnTest
|
||||
* @summary Tests the XPath Number Functions
|
||||
*/
|
||||
public class XPathNumberFnTest extends XPathTestBase {
|
||||
|
||||
private static final Document doc = getDtdDocument();
|
||||
|
||||
/*
|
||||
* DataProvider for testing the number, sum, floor, ceiling and round
|
||||
* functions.
|
||||
* Data columns:
|
||||
* see parameters of the test "testNumberFn"
|
||||
*/
|
||||
@DataProvider(name = "numberExpTestCases")
|
||||
public Object[][] getNumberExp() {
|
||||
return new Object[][]{
|
||||
{"number(1)", 1.0},
|
||||
{"number(-1)", -1.0},
|
||||
{"number(0)", 0},
|
||||
{"number(//Customer[2]/Age)", CUSTOMER_AGES[1]},
|
||||
{"number(//Customer[1]/Age + //Customer[2]/Age)",
|
||||
CUSTOMER_AGES[0] + CUSTOMER_AGES[1]},
|
||||
{"number('abc')", Double.NaN},
|
||||
{"number('')", Double.NaN},
|
||||
{String.format("number(//Age[number()=%d])", CUSTOMER_AGES[1]),
|
||||
CUSTOMER_AGES[1]},
|
||||
{String.format("number(//Age[number(.)=%d])", CUSTOMER_AGES[1]),
|
||||
CUSTOMER_AGES[1]},
|
||||
{"number(//Customer[1]/Name)", Double.NaN},
|
||||
{"number(//Customer[2]/Age + //Customer[1]/Name)", Double.NaN},
|
||||
{"number(true())", 1},
|
||||
{"number(false())", 0},
|
||||
|
||||
{"sum(//Age)", IntStream.of(CUSTOMER_AGES).sum()},
|
||||
{"sum(//Customer[2]/Age)", CUSTOMER_AGES[1]},
|
||||
|
||||
{"floor(1.1)", 1.0},
|
||||
{"floor(-1.6)", -2.0},
|
||||
{"floor(1.0 div 0)", Double.POSITIVE_INFINITY},
|
||||
{"floor(-1.0 div 0)", Double.NEGATIVE_INFINITY},
|
||||
{"floor(true())", 1},
|
||||
{"floor(false())", 0},
|
||||
{"floor(abc)", Double.NaN},
|
||||
{"floor('')", Double.NaN},
|
||||
{"floor(//Customer[2]/Age)", CUSTOMER_AGES[1]},
|
||||
{"floor(//Customer[1]/Name)", Double.NaN},
|
||||
{String.format("number(//Age[floor(.)=%d])", CUSTOMER_AGES[1]),
|
||||
CUSTOMER_AGES[1]},
|
||||
|
||||
{"ceiling(1.1)", 2.0},
|
||||
{"ceiling(-1.4)", -1.0},
|
||||
{"ceiling(1.0 div 0)", Double.POSITIVE_INFINITY},
|
||||
{"ceiling(-1.0 div 0)", Double.NEGATIVE_INFINITY},
|
||||
{"ceiling(true())", 1},
|
||||
{"ceiling(false())", 0},
|
||||
{"ceiling(abc)", Double.NaN},
|
||||
{"ceiling('')", Double.NaN},
|
||||
{"ceiling(//Customer[2]/Age)", CUSTOMER_AGES[1]},
|
||||
{"ceiling(//Customer[1]/Name)", Double.NaN},
|
||||
{String.format("number(//Age[ceiling(.)=%d])",
|
||||
CUSTOMER_AGES[1]), CUSTOMER_AGES[1]},
|
||||
|
||||
{"round(1.49)", 1.0},
|
||||
{"round(1.5)", 2.0},
|
||||
{"round(-1.5)", -1.0},
|
||||
{"round(-1.51)", -2.0},
|
||||
{"round(1.0 div 0)", Double.POSITIVE_INFINITY},
|
||||
{"round(-1.0 div 0)", Double.NEGATIVE_INFINITY},
|
||||
{"round(true())", 1},
|
||||
{"round(false())", 0},
|
||||
{"round(abc)", Double.NaN},
|
||||
{"round('')", Double.NaN},
|
||||
{"round(//Customer[2]/Age)", CUSTOMER_AGES[1]},
|
||||
{"round(//Customer[1]/Name)", Double.NaN},
|
||||
{String.format("number(//Age[round(.)=%d])",
|
||||
CUSTOMER_AGES[1]), CUSTOMER_AGES[1]},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing XPathExpressionException being thrown on
|
||||
* invalid number 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
|
||||
{"//Age[floor()=1.0]"},
|
||||
{"(/Age[ceiling()=1.0]"},
|
||||
{"//Age[round()=1.0]"},
|
||||
{"//Age[sum()]"},
|
||||
|
||||
// Node-set argument is required for these functions
|
||||
{"sum(1)"},
|
||||
{"sum(true())"},
|
||||
{"sum('')"},
|
||||
{"sum('abc')"},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the number, sum, floor, ceiling
|
||||
* and round functions matches the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "numberExpTestCases")
|
||||
void testNumberFn(String exp, double expected) throws Exception {
|
||||
testExp(doc, exp, expected, Double.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));
|
||||
}
|
||||
}
|
||||
384
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathStringFnTest.java
Normal file
384
test/jaxp/javax/xml/jaxp/unittest/xpath/XPathStringFnTest.java
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* 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 8290836
|
||||
* @library /javax/xml/jaxp/unittest
|
||||
* @run testng xpath.XPathStringFnTest
|
||||
* @summary Tests the XPath String Functions
|
||||
*/
|
||||
public class XPathStringFnTest extends XPathTestBase {
|
||||
|
||||
private static final Document doc = getDtdDocument();
|
||||
|
||||
/*
|
||||
* DataProvider for testing the string function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testStringFn"
|
||||
*/
|
||||
@DataProvider(name = "stringExpTestCases")
|
||||
public Object[][] getStringExp() {
|
||||
return new Object[][]{
|
||||
{"string(-0.0)", "0"},
|
||||
{"string(0-1)", "-1"},
|
||||
{"string(1=1)", "true"},
|
||||
{"string(1>2)", "false"},
|
||||
{"string(1+a)", "NaN"},
|
||||
{"string(1.0 div 0)", "Infinity"},
|
||||
{"string(-1.0 div 0)", "-Infinity"},
|
||||
{"string(//Customer/Name)", "name1"},
|
||||
{"string(//Customer[1]/@id)", "x1"},
|
||||
{"string(//Customer/LastName)", ""},
|
||||
{"string(//Customer[1]/Age)",
|
||||
Integer.toString(CUSTOMER_AGES[0])},
|
||||
{"string(number(//Customer[2]/Age))",
|
||||
Integer.toString(CUSTOMER_AGES[1])},
|
||||
{"string(//Customer[1]/Age + //Customer[2]/Age)",
|
||||
Integer.toString(CUSTOMER_AGES[0] + CUSTOMER_AGES[1])},
|
||||
{"string(//Customer[1]/Age + //Customer[1]/Name)", "NaN"},
|
||||
{"string(//Customer[1]/ClubMember='true')", "true"},
|
||||
{"string(//Customer[2]/ClubMember='true')", "false"},
|
||||
{"string(//Customer[1]/ClubMember or " +
|
||||
"//Customer[2]/ClubMember)", "true"},
|
||||
{"string(//Customer[1]/ClubMember and " +
|
||||
"//Customer[2]/ClubMember='true')", "false"},
|
||||
{"string(//*[string()='name2'])", "name2"},
|
||||
{"string(//*[string(.)='name2'])", "name2"},
|
||||
{"string(//*[string(Name)='name2']/Name)", "name2"},
|
||||
{"string(//*[string(@id)='x1']//Street)", "1111 111st ave"},
|
||||
{"string(//*[string(../@id)='x1']/Street)", "1111 111st ave"},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the concat function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testConcatFn"
|
||||
*/
|
||||
@DataProvider(name = "concatExpTestCases")
|
||||
public Object[][] getConcatExp() {
|
||||
return new Object[][]{
|
||||
{"concat('Hello', ' name', 1, true())", "Hello name1true"},
|
||||
{"concat('Hello ', //Customer/Name)", "Hello name1"},
|
||||
{"concat('Hello ', //Customer/LastName)", "Hello "},
|
||||
{"concat('(', //@id, ')')", "(x1)"},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the substring, substring-before and
|
||||
* substring-after functions.
|
||||
* Data columns:
|
||||
* see parameters of the test "testSubstringFn"
|
||||
*/
|
||||
@DataProvider(name = "substringExpTestCases")
|
||||
public Object[][] getSubstringExp() {
|
||||
|
||||
return new Object[][]{
|
||||
{"substring('123@xyz.com', 5, 7)", "xyz.com"},
|
||||
{"substring('123@xyz.com', 5, 10)", "xyz.com"},
|
||||
{"substring(//Email, 5, 7)", "xyz.com"},
|
||||
{"substring(//Email, 5)", "xyz.com"},
|
||||
{"substring(//Email, 1, string-length(.))", "123@xyz.com"},
|
||||
{"substring(//Email, 1, string-length(.)+1)", "123@xyz.com"},
|
||||
{"substring(//LastName, 1)", ""},
|
||||
{"string(//*[substring(., 1)='name2'])", "name2"},
|
||||
|
||||
{"substring-before('123@xyz.com', '@')", "123"},
|
||||
{"substring-before(//Email, '@')", "123"},
|
||||
{"substring-before(//Email, '?')", ""},
|
||||
{"substring-before(//Email, '')", ""},
|
||||
{"substring-before(//LastName, '')", ""},
|
||||
{"string(//*[substring-before(., ' ')='1111'])", "1111 111st " +
|
||||
"ave"},
|
||||
|
||||
{"substring-after('123@xyz.com', '@')", "xyz.com"},
|
||||
{"substring-after(//Email, '@')", "xyz.com"},
|
||||
{"substring-after(//Email, '?')", ""},
|
||||
{"substring-after(//Email, '')", "123@xyz.com"},
|
||||
{"substring-after(//LastName, '')", ""},
|
||||
{"string(//*[substring-after(., ' ')='111st ave'])", "1111 " +
|
||||
"111st ave"},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the normalize-space function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testNormalizeSpaceFn"
|
||||
*/
|
||||
@DataProvider(name = "normalizeExpTestCases")
|
||||
public Object[][] getNormalizeExp() {
|
||||
return new Object[][]{
|
||||
{"normalize-space(' 1111 111st ave ')", "1111 111st ave"},
|
||||
{"normalize-space(true())", "true"},
|
||||
{"normalize-space(1.234)", "1.234"},
|
||||
{"normalize-space(//Customer[1]//Street)", "1111 111st ave"},
|
||||
{"normalize-space(//Customer[2]//Street)", "2222 222nd ave"},
|
||||
{"normalize-space(//LastName)", ""},
|
||||
{"string(//*[normalize-space()='name1'])", "name1"},
|
||||
{"string(//*[normalize-space(.)='name1'])", "name1"},
|
||||
{"string(//*[normalize-space(Name)='name2']/Name)", "name2"},
|
||||
{"string(//*[normalize-space(@id)='x1']//Street)", "1111 " +
|
||||
"111st ave"},
|
||||
{"string(//*[normalize-space(../@id)='x1']/Street)", "1111 " +
|
||||
"111st ave"},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the translate function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testTranslateFn"
|
||||
*/
|
||||
@DataProvider(name = "translateExpTestCases")
|
||||
public Object[][] getTranslateExp() {
|
||||
return new Object[][]{
|
||||
{"translate('1111 111st ave', ' ', '')", "1111111stave"},
|
||||
{"translate('1111 111st ave', '', '')", "1111 111st ave"},
|
||||
{"translate('1111 111st ave', '1 ', '')", "stave"},
|
||||
{"translate('abcabcdcd', 'abcd', 'xyz')", "xyzxyzz"},
|
||||
{"translate('abcabcdcd', 'bcd', 'uvwxyz')", "auvauvwvw"},
|
||||
{"translate('aabccdacbabcb', 'aaccbbdd', 'wxyz')", "wwyywywy"},
|
||||
{"translate(//Customer[1]//Street, " +
|
||||
"'abcdefghijklmnopqrstuvwxyz', " +
|
||||
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ')",
|
||||
"1111 111ST AVE"},
|
||||
{"translate(//LastName, 'name', 'NAME')", ""},
|
||||
{"translate(true(), true(), false())", "fals"},
|
||||
{"translate(123, 2, 3)", "133"},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the string-length function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testStringLengthFn"
|
||||
*/
|
||||
@DataProvider(name = "stringLengthExpTestCases")
|
||||
public Object[][] getStringLengthExp() {
|
||||
return new Object[][]{
|
||||
{"string-length('')", 0},
|
||||
{"string-length(123)", 3},
|
||||
{"string-length(true())", 4},
|
||||
{"string-length('1111 111st ave')", 14.0},
|
||||
{"string-length(//Customer[1]//Street)", 14.0},
|
||||
{"string-length(//LastName)", 0},
|
||||
{"string-length(//Customer[1]/Name)", 5},
|
||||
{"string-length(//Customer[1]/@id)", 2},
|
||||
{"string-length(name(//*[string-length()=10]))", 5},
|
||||
{"string-length(name(//*[string-length(.)=10]))", 5},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the starts-with function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testStartsWithFn"
|
||||
*/
|
||||
@DataProvider(name = "startsWithExpTestCases")
|
||||
public Object[][] getStartsWithExp() {
|
||||
return new Object[][]{
|
||||
{"starts-with(//Email, '123')", true},
|
||||
{"starts-with(//Email, 123)", true},
|
||||
{"starts-with(//Email, '?')", false},
|
||||
{"starts-with(//Email, '')", true},
|
||||
{"starts-with(//Customer/@id, 'x')", true},
|
||||
{"starts-with(//LastName, '')", true},
|
||||
{"boolean(//*[starts-with(., 'name2')]='name2')", true},
|
||||
{"boolean(//*[starts-with(text(), 'name')]='name2')", true},
|
||||
{"boolean(//*[starts-with(., 'name1')]/.='name2')", false},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing the contains function.
|
||||
* Data columns:
|
||||
* see parameters of the test "testContainsFn"
|
||||
*/
|
||||
@DataProvider(name = "containsExpTestCases")
|
||||
public Object[][] getContainsExp() {
|
||||
return new Object[][]{
|
||||
{"contains(//Email, '123')", true},
|
||||
{"contains(//Email, 123)", true},
|
||||
{"contains(//Email, '?')", false},
|
||||
{"contains(//Email, '')", true},
|
||||
{"contains(//Customer/@id, 'x')", true},
|
||||
{"contains(//LastName, '')", true},
|
||||
{"boolean(//*[contains(., 'name2')]='name2')", true},
|
||||
{"boolean(//*[contains(text(), 'name')]='name2')", true},
|
||||
{"boolean(//*[contains(., 'name1')]/.='name2')", false},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider for testing XPathExpressionException being thrown on
|
||||
* invalid string function usage.
|
||||
* Data columns:
|
||||
* see parameters of the test "testExceptionOnEval"
|
||||
*/
|
||||
@DataProvider(name = "exceptionExpTestCases")
|
||||
public Object[][] getExceptionExp() {
|
||||
return new Object[][]{
|
||||
// At least two arguments are required for these functions
|
||||
{"//*[concat()='name2']"},
|
||||
{"//*[concat(.)='name2']"},
|
||||
{"//*[substring()='name2']"},
|
||||
{"//*[substring(.)='name2']"},
|
||||
{"//*[substring-before()='name2']"},
|
||||
{"//*[substring-before(.)='name2']"},
|
||||
{"//*[substring-after()='name2']"},
|
||||
{"//*[substring-after(.)='name2']"},
|
||||
{"//*[translate()='name2']"},
|
||||
{"//*[translate(.)='name2']"},
|
||||
{"//*[contains()]"},
|
||||
{"//*[contains(.)]"},
|
||||
{"//*[starts-with()]"},
|
||||
{"//*[starts-with(.)]"},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the string function matches
|
||||
* the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "stringExpTestCases")
|
||||
void testStringFn(String exp, String expected) throws Exception {
|
||||
testExp(doc, exp, expected, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the concat function matches
|
||||
* the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "concatExpTestCases")
|
||||
void testConcatFn(String exp, String expected) throws Exception {
|
||||
testExp(doc, exp, expected, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the substring, substring-before
|
||||
* and substring-after functions matches the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "substringExpTestCases")
|
||||
void testSubstringFn(String exp, String expected) throws Exception {
|
||||
testExp(doc, exp, expected, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the normalize-space function
|
||||
* matches the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "normalizeExpTestCases")
|
||||
void testNormalizeSpaceFn(String exp, String expected) throws Exception {
|
||||
testExp(doc, exp, expected, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the translate function matches
|
||||
* the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "translateExpTestCases")
|
||||
void testTranslateFn(String exp, String expected) throws Exception {
|
||||
testExp(doc, exp, expected, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the string-length function matches
|
||||
* the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "stringLengthExpTestCases")
|
||||
void testStringLengthFn(String exp, double expected) throws Exception {
|
||||
testExp(doc, exp, expected, Double.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the starts-with function
|
||||
* matches the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "startsWithExpTestCases")
|
||||
void testStartsWithFn(String exp, boolean expected) throws Exception {
|
||||
testExp(doc, exp, expected, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the result of evaluating the contains function matches
|
||||
* the expected result.
|
||||
*
|
||||
* @param exp XPath expression
|
||||
* @param expected expected result
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
@Test(dataProvider = "containsExpTestCases")
|
||||
void testContainsFn(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));
|
||||
}
|
||||
}
|
||||
@ -29,15 +29,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import javax.xml.xpath.XPathNodes;
|
||||
import javax.xml.xpath.XPathEvaluationResult;
|
||||
import javax.xml.xpath.*;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
@ -52,11 +50,13 @@ class XPathTestBase {
|
||||
static final String DTD = """
|
||||
<!DOCTYPE Customers [
|
||||
<!ELEMENT Customers (Customer*)>
|
||||
<!ELEMENT Customer (Name, Phone, Email, Address)>
|
||||
<!ELEMENT Customer (Name, Phone, Email, Address, Age, ClubMember)>
|
||||
<!ELEMENT Name (#PCDATA)>
|
||||
<!ELEMENT Phone (#PCDATA)>
|
||||
<!ELEMENT Email (#PCDATA)>
|
||||
<!ELEMENT Address (Street, City, State)>
|
||||
<!ELEMENT Age (#PCDATA)>
|
||||
<!ELEMENT ClubMember (#PCDATA)>
|
||||
<!ELEMENT Street (#PCDATA)>
|
||||
<!ELEMENT City (#PCDATA)>
|
||||
<!ELEMENT State (#PCDATA)>
|
||||
@ -67,7 +67,7 @@ class XPathTestBase {
|
||||
""";
|
||||
|
||||
static final String RAW_XML
|
||||
= "<Customers xmlns:foo=\"foo\">"
|
||||
= "<Customers xmlns:foo=\"foo\" xml:lang=\"en\">"
|
||||
+ " <Customer id=\"x1\">"
|
||||
+ " <Name>name1</Name>"
|
||||
+ " <Phone>1111111111</Phone>"
|
||||
@ -77,16 +77,20 @@ class XPathTestBase {
|
||||
+ " <City>The City</City>"
|
||||
+ " <State>The State</State>"
|
||||
+ " </Address>"
|
||||
+ " <Age>0</Age>"
|
||||
+ " <ClubMember>true</ClubMember>"
|
||||
+ " </Customer>"
|
||||
+ " <Customer id=\"x2\">"
|
||||
+ " <Name>name2</Name>"
|
||||
+ " <Phone>2222222222</Phone>"
|
||||
+ " <Email id=\"y\">123@xyz.com</Email>"
|
||||
+ " <Address>"
|
||||
+ " <Street>2222 222nd ave</Street>"
|
||||
+ " <Street> 2222 222nd ave </Street>"
|
||||
+ " <City>The City</City>"
|
||||
+ " <State>The State</State>"
|
||||
+ " </Address>"
|
||||
+ " <Age>100</Age>"
|
||||
+ " <ClubMember>false</ClubMember>"
|
||||
+ " </Customer>"
|
||||
+ " <Customer id=\"x3\">"
|
||||
+ " <Name>name3</Name>"
|
||||
@ -97,6 +101,8 @@ class XPathTestBase {
|
||||
+ " <City>The City</City>"
|
||||
+ " <State>The State</State>"
|
||||
+ " </Address>"
|
||||
+ " <Age>-100</Age>"
|
||||
+ " <ClubMember>false</ClubMember>"
|
||||
+ " </Customer>"
|
||||
+ " <foo:Customer foo:id=\"x1\">"
|
||||
+ " <foo:Name>name1</foo:Name>"
|
||||
@ -107,21 +113,28 @@ class XPathTestBase {
|
||||
+ " <foo:City>The City</foo:City>"
|
||||
+ " <foo:State>The State</foo:State>"
|
||||
+ " </foo:Address>"
|
||||
+ " <foo:Age>0</foo:Age>"
|
||||
+ " <foo:ClubMember>true</foo:ClubMember>"
|
||||
+ " </foo:Customer>"
|
||||
+ "</Customers>";
|
||||
|
||||
// Number of root element.
|
||||
final int ROOT = 1;
|
||||
// Number of Customer elements.
|
||||
final int LANG_ATTRIBUTES = 1;
|
||||
final int CUSTOMERS = 3;
|
||||
// Number of id attributes.
|
||||
final int ID_ATTRIBUTES = 6;
|
||||
// Number of child elements of Customer.
|
||||
final int CUSTOMER_ELEMENTS = 7;
|
||||
final int CUSTOMER_ELEMENTS = 6;
|
||||
// Number of Address elements.
|
||||
final int ADDRESS_ELEMENTS = 3;
|
||||
// Number of Customer in the foo namespace.
|
||||
final int FOO_CUSTOMERS = 1;
|
||||
// Number of id attributes in the foo namespace.
|
||||
final int FOO_ID_ATTRIBUTES = 2;
|
||||
// Customer Ages
|
||||
final int[] CUSTOMER_AGES = {0, 100, -100, 0};
|
||||
|
||||
/**
|
||||
* Returns a {@link org.w3c.dom.Document} for XML with DTD.
|
||||
@ -187,6 +200,47 @@ class XPathTestBase {
|
||||
assertFalse(true, "Unsupported type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates XPath expression and checks if it matches the expected result.
|
||||
*
|
||||
* @param doc xml document {@link org.w3c.dom.Document}
|
||||
* @param exp xpath expression string
|
||||
* @param expected expected result
|
||||
* @param clazz expected result type for evaluation.
|
||||
* @param <T> expected result type
|
||||
*
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
static <T> void testExp(Document doc, String exp, T expected,
|
||||
Class<T> clazz) throws Exception {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
T result = xPath.evaluateExpression(exp, doc, clazz);
|
||||
T result2 = (T) xPath.evaluate(exp, doc,
|
||||
XPathEvaluationResult.XPathResultType.getQNameType(clazz));
|
||||
|
||||
Assert.assertEquals(result, expected);
|
||||
Assert.assertEquals(result2, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates XPath expression.
|
||||
*
|
||||
* @param doc xml document {@link org.w3c.dom.Document}
|
||||
* @param exp xpath expression string
|
||||
*
|
||||
* @throws Exception if test fails
|
||||
*/
|
||||
static void testEval(Document doc, String exp) throws Exception {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
try {
|
||||
xPath.evaluateExpression(exp, doc);
|
||||
} catch (XPathExpressionException e) {
|
||||
xPath.evaluate(exp, doc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DataProvider: XPath object
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user