# Features covered: XPath capabilities
#
# This file contains a collection of tests for the XPath engine of
# tDOM.
# Tested commands and object commands:
# xpath-1.*: Function tests
# xpath-2.*: i18n
# xpath-3.*: NaN/Inf
# xpath-4.*: Tcl coded XPath functions and additional Tcl coded
# XPath functions
# xpath-5.*: erroneous XPath exprs
# xpath-6.*: Doc order after modifying tree
# xpath-7.*: Asorted XPath expressions, which are not occur in the xslt
# tests outside this tcltest based test suite
#
# Copyright (c) 2002 Rolf Ade.
#
# RCS: @(#) $Id: xpath.test,v 1.16 2004/07/28 03:43:10 rolf Exp $
source [file join [file dir [info script]] loadtdom.tcl]
test xpath-1.1 {function normalize-space} {
set doc [dom createDocument foo]
set root [$doc documentElement]
set r [$root selectNodes {normalize-space('f ')}]
$doc delete
string length $r
} {1}
set doc [dom createDocument foo]
set root [$doc documentElement]
test xpath-1.2 {starts-with, according errata to section 4.2} {
$root selectNodes {starts-with('someString','')}
} {1}
test xpath-1.3 {starts-with, according errata to section 4.2} {
$root selectNodes {starts-with('','')}
} {1}
test xpath-1.4 {contains, according errata to section 4.2} {
$root selectNodes {contains('someString','')}
} {1}
test xpath-1.5 {contains, according errata to section 4.2} {
$root selectNodes {contains('','')}
} {1}
test xpath-1.6 {substring-before, according errata to section 4.2} {
$root selectNodes {substring-before('someString','')}
} {}
test xpath-1.7 {substring-before, according errata to section 4.2} {
$root selectNodes {substring-before('','')}
} {}
test xpath-1.8 {substring-after, according errata to section 4.2} {
$root selectNodes {substring-after('someString','')}
} {someString}
test xpath-1.9 {substring-after, according errata to section 4.2} {
$root selectNodes {substring-after('','')}
} {}
test xpath-1.10 {floor, according errata to section 4.4} {
$root selectNodes {floor('notANumber')}
} {NaN}
test xpath-1.11 {floor, according errata to section 4.4} {
$root selectNodes {floor('+3.2')}
} {NaN}
test xpath-1.12 {floor, according errata to section 4.4} {
$root selectNodes {floor('3.2e2')}
} {NaN}
test xpath-1.13 {ceiling, according errata to section 4.4} {
$root selectNodes {ceiling('notANumber')}
} {NaN}
test xpath-1.14 {ceiling, according errata to section 4.4} {
$root selectNodes {ceiling('+3.2')}
} {NaN}
test xpath-1.15 {ceiling, according errata to section 4.4} {
$root selectNodes {ceiling('3.2e2')}
} {NaN}
$doc delete
test xpath-2.1 {non ASCII chars in element names} {
set doc [dom parse "<\u00e4\u00f6\u00fc\u00df/>"]
set root [$doc documentElement]
set nodes [$root selectNodes /\u00e4\u00f6\u00fc\u00df]
$doc delete
llength $nodes
} {1}
set doc [dom createDocument foo]
set root [$doc documentElement]
test xpath-3.1 {positive number mod by 0} {
$root selectNodes {4 mod 0}
} {NaN}
test xpath-3.2 {0 mod 0} {
$root selectNodes {0 mod 0}
} {NaN}
test xpath-3.3 {negative number mod 0} {
$root selectNodes {-1 mod 0}
} {NaN}
test xpath-3.4 {positive number div by 0} {
$root selectNodes {4 div 0}
} {Infinity}
test xpath-3.5 {0 div 0} {
$root selectNodes {0 div 0}
} {NaN}
test xpath-3.6 {negative div 0} {
$root selectNodes {-4 div 0}
} {-Infinity}
test xpath-3.7 {number value of a literal} {
$root selectNodes {number('foobar')}
} {NaN}
test xpath-3.8 {number value of an empty node set} {
$root selectNodes {number(noChilds)}
} {NaN}
test xpath-3.9 {propagation of NaN throu multiplication} {
$root selectNodes {2 * (4 mod 0)}
} {NaN}
test xpath-3.10 {propagation of Infinity throu multiplication} {
$root selectNodes {2 * (4 div 0)}
} {Infinity}
test xpath-3.11 {propagation of Infinity throu multiplication} {
$root selectNodes {-2 * (3 div 0)}
} {-Infinity}
test xpath-3.12 {propagation of Infinity throu multiplication} {
$root selectNodes {2 * (-7 div 0)}
} {-Infinity}
test xpath-3.13 {propagation of Infinity throu multiplication} {
$root selectNodes {-2 * (-23 div 0)}
} {Infinity}
test xpath-3.14 {multiplication of Infinity with Infinity} {
$root selectNodes {(2 div 0) * (3 div 0)}
} {Infinity}
test xpath-3.15 {multiplication of Infinity with -Infinity} {
$root selectNodes {(2 div 0) * (-3 div 0)}
} {-Infinity}
test xpath-3.16 {positive number divided by Infinity} {
$root selectNodes {2 div (23 div 0)}
} {0}
test xpath-3.17 {negative number divided by Infinity} {
$root selectNodes {-2 div (23 div 0)}
} {0}
test xpath-3.18 {positive number divided by -Infinity} {
$root selectNodes {2 div (-23 div 0)}
} {0}
test xpath-3.19 {negative number divided by -Infinity} {
$root selectNodes {-2.2 div (-23.7 div 0)}
} {0}
test xpath-3.20 {Infinity divided by Infinity} {
$root selectNodes {(2 div 0) div (3 div 0)}
} {NaN}
test xpath-3.21 {Infinity divided by postive number} {
$root selectNodes {(2.7 div 0) div 23}
} {Infinity}
test xpath-3.22 {Infinity divided by negative number} {
$root selectNodes {(2.7 div 0) div -23}
} {-Infinity}
test xpath-3.23 {-Infinity divided by postive number} {
$root selectNodes {(-2.7 div 0) div 23}
} {-Infinity}
test xpath-3.24 {-Infinity divided by negative number} {
$root selectNodes {(-2.7 div 0) div -23}
} {Infinity}
test xpath-3.25 {Infinity divided by NaN} {
$root selectNodes {(2 div 0) div (2 mod 0)}
} {NaN}
test xpath-3.26 {NaN divided by Infinity} {
$root selectNodes {(2 mod 0) div (2 div 0)}
} {NaN}
test xpath-3.27 {Infinity divided by zero} {
$root selectNodes {(2 div 0) div 0}
} {Infinity}
test xpath-3.28 {-Infinity divided by zero} {
$root selectNodes {(-2 div 0) div 0}
} {-Infinity}
test xpath-3.29 {Infinity plus positive number} {
$root selectNodes {(1 div 0) + 345}
} {Infinity}
test xpath-3.30 {Infinity minus positive number} {
$root selectNodes {(1 div 0) - 5}
} {Infinity}
test xpath-3.31 {number minus Infinity} {
$root selectNodes {27 - (1 div 0)}
} {-Infinity}
test xpath-3.32 {number minus -Infinity} {
$root selectNodes {5 - (-1 div 0)}
} {Infinity}
test xpath-3.33 {Infinity plus Infinity} {
$root selectNodes {(1 div 0) + (1 div 0)}
} {Infinity}
test xpath-3.34 {Infinity plus -Infinity} {
$root selectNodes {(1 div 0) + (-1 div 0)}
} {NaN}
test xpath-3.35 {Infinity minus -Infinity} {
$root selectNodes {(1 div 0) - (-1 div 0)}
} {Infinity}
$doc delete
set doc [dom parse {Foo}]
set root [$doc documentElement]
test xpath-4.1 {function-available} {
$root selectNodes function-available('count')
} {1}
test xpath-4.2 {function-available} {
$root selectNodes function-available('foobar')
} {0}
test xpath-4.3 {system-property} {
$root selectNodes system-property('xsl:version')
} {1.0}
proc ::dom::xpathFunc::mycontains {ctxNode pos nodeListNode nodeList args} {
if {[llength $args] != 4} {
error "mycontains(): wrong # of args!"
}
foreach {arg1Typ arg1Value arg2Typ arg2Value} $args break
set text [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
set str [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value]
if {[string first [string tolower $str] [string tolower $text]] != -1} {
return [list bool true]
} else {
return [list bool false]
}
}
test xpath-4.4 {tcl coded additional XPath function} {
$root selectNodes {mycontains(., 'fo')}
} {1}
test xpath-4.5 {tcl coded additional XPath function} {
$root selectNodes {mycontains(., 'bo')}
} {0}
test xpath-4.6 {tcl coded additional XPath function - error reported} {
catch {$root selectNodes {mycontains(., 'bo', 'ba')}} errMsg
set errMsg
} {Tcl error while executing XPATH extension function 'mycontains':
mycontains(): wrong # of args!}
proc ::dom::xpathFunc::wrongreturn {ctxNode pos nodeListNode nodeList args} {
return [list footype "foo"]
}
test xpath-4.7 {tcl coded additional XPath function - unknown return type} {
catch {$root selectNodes {wrongreturn('foo')}} errMsg
set errMsg
} {Unknown type of return value "footype" from tcl coded XPath function "wrongreturn"!}
proc ::dom::xpathFunc::returnnumber {ctxNode pos nodeListNode nodeList args} {
return [list number "42"]
}
test xpath-4.8 {tcl coded additional XPath function - return number} {
$root selectNodes {returnnumber()}
} {42}
test xpath-4.9 {tcl coded XPath function - erroneous function name} {
catch {$root selectNodes {thisFunctiondoesNotExists('foo',.)}} errMsg
set errMsg
} {Unknown XPath function: "thisFunctiondoesNotExists"!}
test xpath-4.10 {full qualified tcl coded XPath function - erroneous prefix} {
catch {$root selectNodes notdefinedprefix:mycontains()} errMsg
set errMsg
} {There isn't a namespace bound to the prefix.}
namespace eval ::dom::xpathFunc::myNS {
proc mycontains {ctxNode pos nodeListNode nodeList args} {
if {[llength $args] != 4} {
error "myNS::mycontains(): wrong # of args!"
}
foreach {arg1Typ arg1Value arg2Typ arg2Value} $args break
set text [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
set str [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value]
if {[string first [string tolower $str] [string tolower $text]] != -1} {
return [list bool true]
} else {
return [list bool false]
}
}
}
test xpath-4.11 {full qualified tcl coded XPath function} {
$root selectNodes {myNS:mycontains(., 'fo')}
} {1}
test xpath-4.12 {full qualified tcl coded XPath function} {
$root selectNodes {myNS:mycontains(., 'bo')}
} {0}
test xpath-4.13 {error in arg expr of tcl coded XPath function} {
catch {$root selectNodes {mycontains(foo::bar, 'bo')}}
} {1}
test xpath-4.14 {error in arg expr of full qual. tcl coded XPath function} {
catch {$root selectNodes {myNS:mycontains(foo::bar, 'bo')}}
} {1}
proc ::dom::xpathFunc::buggyproc {ctxNode pos nodeListNode nodeList args} {
if {[llength $args] != 2} {
error "returnstring(): wrong # of args!"
}
foreach {arg1Typ arg1Value} $args break
set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
# There isn't a [string split ..] - this will trigger the tcl error
set charList [string split $str ""]
set result ""
foreach char $charList {
set result $char$result
}
return [list string $result]
}
test xpath-4.15 {tcl coded XPath function - tcl error in XPath func} {
catch {$root selectNodes {buggyproc('bambo')}}
} {1}
proc ::dom::xpathFunc::returnstring {ctxNode pos nodeListNode nodeList args} {
if {[llength $args] != 2} {
error "returnstring(): wrong # of args!"
}
foreach {arg1Typ arg1Value} $args break
set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
set charList [split $str ""]
set result ""
foreach char $charList {
set result $char$result
}
return [list string $result]
}
test xpath-4.16 {tcl coded additional XPath function - tcl error in XPath func} {
$root selectNodes {returnstring('bambo')}
} {obmab}
proc ::dom::xpathFunc::returnnodes {ctxNode pos nodeListNode nodeList args} {
if {[llength $args] != 2} {
error "returnnodes(): wrong # of args!"
}
foreach {arg1Typ arg1Value} $args break
if {$arg1Typ != "nodes"} {
error "returnnodes(): argument must be a nodeset"
}
set node [[lindex $arg1Value 0] selectNodes {/*[1]}]
# This returns a node list with 2 nodes. Since both nodes are
# the same, this node only shows up one time in the result set
# of the query
return [list nodes [list $node $node]]
}
test xpath-4.17 {tcl coded additional XPath function - return nodes} {
set queryresult [$root selectNodes {returnnodes(.)}]
if {$queryresult == $root} {
set result 1
} else {
set result 0
}
set result
} {1}
# Called from ::dom::xpathFunc::errorStack
proc ::dom::xpathFunc::errorStack1 {} {
error "Some error"
}
proc ::dom::xpathFunc::errorStack {ctxNode pos nodeListNode nodeList args} {
errorStack1
return [list string "Not reached"]
}
test xpath-4.18 {error stack in tcl coded additional XPath function} {
set result [catch {$root selectNodes errorStack()} errMsg]
lappend result $errMsg
} {1 {Tcl error while executing XPATH extension function 'errorStack':
Some error}}
test xpath-5.1 {erroneous XPath expr: missing right brace in predicate} {
set result [catch {$root selectNodes {*[1}} errMsg]
list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1'
Parsed symbols:
0 WCARDNAME 0 0.000 0 *
1 LBRACKET 0 0.000 1
2 INTNUMBER 1 1.000 2 }}
test xpath-5.2 {erroneous XPath expr: missing right brace in predicate} {
set result [catch {$root selectNodes {*[1][@attr}} errMsg]
list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1][@attr'
Parsed symbols:
0 WCARDNAME 0 0.000 0 *
1 LBRACKET 0 0.000 1
2 INTNUMBER 1 1.000 2
3 RBRACKET 0 0.000 3
4 LBRACKET 0 0.000 4
5 ATTRIBUTE 0 0.000 9 attr}}
test xpath-5.3 {erroneous XPath expr: missing left brace in predicate} {
catch {$root selectNodes {*1]}}
} {1}
test xpath-5.4 {erroneous XPath expr} {
catch {$root selectNodes {foo: bar}} errMsg
set errMsg
} {Illegal character in localname}
test xpath-5.5 {erroneous XPath expr} {
catch {$root selectNodes {foo :bar}} errMsg
set errMsg
} {Unexpected token ':'}
test xpath-5.6 {erroneous XPath expr} {
catch {$root selectNodes {:foo}} errMsg
set errMsg
} {Unexpected token ':'}
$doc delete
test xpath-5.7 {using 'xslt variable' in expr} {
set doc [dom parse {}]
set root [$doc documentElement]
set result [catch {$root selectNodes {elem[@id='$var']}} errMsg]
$doc delete
lappend result $errMsg
} {0 {}}
set doc [dom parse {
asub2
asub3
asub4
bsub1
bsub2
}]
set root [$doc documentElement]
test xpath-6.1 {document order in modified DOM tree} {
set newAsub [$doc createElement asub]
$newAsub appendChild [$doc createTextNode "asub1"]
$root insertBefore $newAsub [$root firstChild]
set result ""
foreach node [$root selectNodes {bsub|asub}] {
append result "[$node text] "
}
set result
} {asub1 asub2 asub3 asub4 bsub1 bsub2 }
$doc delete
set doc [dom parse {
}]
set root [$doc documentElement]
test xpath-7.1 {preceding-sibling axis with documentElement als current node} {
$root selectNodes {count(preceding-sibling::node())}
} {4}
test xpath-7.2 {following-sibling axis with documentElement als current node} {
$root selectNodes {count(following-sibling::node())}
} {4}
$doc delete
test xpath-7.3 {NCName equal to an operator in a union expr} {
dom parse {} doc
$doc documentElement root
set node [$root selectNodes {p|div}]
set result [$node nodeName]
$doc delete
set result
} {div}
test xpath-7.4 {Name test * in a union expr} {
dom parse {} doc
$doc documentElement root
set node [$root selectNodes {processing-instruction()|*}]
set result [$node nodeName]
$doc delete
set result
} {div}
# cleanup
::tcltest::cleanupTests
return