Skip to content

Commit

Permalink
Xspec 1.2.0. update.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexJitianu committed Feb 11, 2019
1 parent 33d2c6b commit 3ec0b78
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 41 deletions.
2 changes: 1 addition & 1 deletion frameworks/xspec/src/ant/find-test-failure.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<xsl:template as="element(xspec)" match="document-node()">
<xspec>
<passed>
<xsl:value-of select="empty(//x:*[@successful = 'false'])" />
<xsl:value-of select="empty(//x:scenario/x:test/@successful[not(xs:boolean(.))])" />
</passed>
</xspec>
</xsl:template>
Expand Down
1 change: 1 addition & 0 deletions frameworks/xspec/src/ant/get-schematron-phase.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Output XML structure is for Ant <xmlproperty> task.
-->
<xsl:template as="element(xspec)" match="document-node()">
<!-- "xspec.phase" property: Documented in Wiki. DO NOT RENAME. -->
<xspec>
<phase>
<!-- TODO: @href and @select should be taken into account -->
Expand Down
50 changes: 44 additions & 6 deletions frameworks/xspec/src/compiler/generate-common-tests.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -57,32 +57,60 @@

<xsl:function name="x:gather-specs" as="element(x:description)+">
<xsl:param name="visit" as="element(x:description)+"/>

<!-- "$visit/x:import" without sorting -->
<xsl:variable name="imports" as="element(x:import)*">
<xsl:for-each select="$visit">
<xsl:sequence select="x:import" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="imports" as="element(x:import)*"
select="$visit/x:import"/>
select="x:distinct-nodes-stable($imports)" />

<!-- "document($imports/@href)" without sorting -->
<xsl:variable name="docs" as="document-node(element(x:description))*">
<xsl:for-each select="$imports">
<xsl:sequence select="document(@href)" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="docs" as="document-node(element(x:description))*"
select="x:distinct-nodes-stable($docs)" />

<!-- "$docs/x:description" without sorting -->
<xsl:variable name="imported" as="element(x:description)*">
<xsl:for-each select="$docs">
<xsl:sequence select="x:description" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="imported" as="element(x:description)*"
select="document($imports/@href)/x:description"/>
select="x:distinct-nodes-stable($imported)" />

<!-- "$imported except $visit" without sorting -->
<xsl:variable name="imported-except-visit" as="element(x:description)*"
select="$imported[empty($visit intersect .)]"/>

<xsl:choose>
<xsl:when test="empty($imported except $visit)">
<xsl:when test="empty($imported-except-visit)">
<xsl:sequence select="$visit"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="x:gather-specs($visit | $imported)"/>
<xsl:sequence select="x:gather-specs(($visit, $imported-except-visit))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

<xsl:template match="x:description" mode="x:gather-specs">
<xsl:apply-templates mode="x:gather-specs">
<xsl:with-param name="xslt-version" tunnel="yes" select="
( @xslt-version, '2.0' )[1]"/>
( @xslt-version, 2.0 )[1]"/>
<xsl:with-param name="preserve-space" tunnel="yes" select="
for $qname in tokenize(@preserve-space, '\s+') return
resolve-QName($qname, .)"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="x:scenario" mode="x:gather-specs">
<xsl:param name="xslt-version" as="xs:string" tunnel="yes" required="yes"/>
<xsl:param name="xslt-version" as="xs:decimal" tunnel="yes" required="yes"/>
<x:scenario xslt-version="{$xslt-version}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates mode="x:gather-specs"/>
Expand Down Expand Up @@ -529,6 +557,16 @@
</xsl:copy>
</xsl:template>

<!-- Removes duplicate nodes from a sequence of nodes. (Removes a node if it appears
in a prior position of the sequence.)
This function does not sort nodes in document order.
Based on http://www.w3.org/TR/xpath-functions-31/#func-distinct-nodes-stable -->
<xsl:function name="x:distinct-nodes-stable" as="node()*">
<xsl:param name="nodes" as="node()*"/>

<xsl:sequence select="$nodes[empty(subsequence($nodes, 1, position() - 1) intersect .)]"/>
</xsl:function>

<!--
Debugging tool. Return a human-readable path of a node.
-->
Expand Down
2 changes: 1 addition & 1 deletion frameworks/xspec/src/compiler/generate-query-utils.xql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ declare function test:deep-equal($seq1 as item()*, $seq2 as item()*) as xs:boole
declare function test:deep-equal(
$seq1 as item()*,
$seq2 as item()*,
$version as xs:double
$version as xs:decimal
) as xs:boolean
{
if ( $version = 1.0 ) then
Expand Down
50 changes: 46 additions & 4 deletions frameworks/xspec/src/compiler/generate-tests-utils.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<xsl:function name="test:deep-equal" as="xs:boolean">
<xsl:param name="seq1" as="item()*"/>
<xsl:param name="seq2" as="item()*"/>
<xsl:param name="version" as="xs:double"/>
<xsl:param name="version" as="xs:decimal"/>
<!-- Using a $param in @use-when does not work. TODO: What to do? At run time? -->
<!--xsl:if test="$seq1 instance of node()" use-when="$debug">
<xsl:message select="'DEEP-EQUAL: SEQ1:', x:node-path($seq1)"/>
Expand Down Expand Up @@ -258,8 +258,10 @@
<xsl:when test="($node1 instance of attribute() and
$node2 instance of attribute()) or
($node1 instance of processing-instruction() and
$node2 instance of processing-instruction())">
<xsl:sequence select="node-name($node1) eq node-name($node2) and
$node2 instance of processing-instruction()) or
(test:instance-of-namespace($node1) and
test:instance-of-namespace($node2))">
<xsl:sequence select="deep-equal(node-name($node1), node-name($node2)) and
(string($node1) eq string($node2) or string($node1) = '...')" />

</xsl:when>
Expand Down Expand Up @@ -304,7 +306,7 @@
</xsl:choose>
<xsl:choose>
<xsl:when test="count($value//node()) > 1000">
<!-- Ensure that a unique file name is generated by creating a copy of the result (xspec issue #67). -->
<!-- Ensure that a unique file name is generated by creating a copy of the result (expath/xspec#67). -->
<xsl:variable name="value-copy">
<xsl:copy-of select="$value"/>
</xsl:variable>
Expand Down Expand Up @@ -447,6 +449,46 @@
<xsl:sequence select="$rtf" />
</xsl:function>

<!-- Returns true if item is namespace node -->
<xsl:function name="test:instance-of-namespace" as="xs:boolean">
<xsl:param name="item" as="item()?"/>

<!-- Unfortunately there is no such test as "instance of namespace()":
http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200608/msg00719.html -->
<xsl:sequence select="$item instance of node()
and not($item instance of attribute()
or $item instance of comment()
or $item instance of document-node()
or $item instance of element()
or $item instance of processing-instruction()
or $item instance of text())" />
</xsl:function>

<!-- Returns true if item is node and can be wrapped in document node -->
<xsl:function name="test:wrappable-node" as="xs:boolean">
<xsl:param name="item" as="item()" />

<!-- Document node cannot wrap attribute node or namespace node:
http://www.w3.org/TR/xslt20/#err-XTDE0420 -->
<xsl:sequence select="$item instance of node()
and not($item instance of attribute()
or test:instance-of-namespace($item))" />
</xsl:function>

<!-- Wraps nodes in document node with their type annotations kept -->
<xsl:function name="test:wrap-nodes" as="document-node()">
<xsl:param name="nodes" as="node()*" />

<!-- $wrap aims to create an implicit document node as described
in http://www.w3.org/TR/xslt20/#temporary-trees
So its xsl:variable must not have @as or @select.
Do not use xsl:document or xsl:copy-of: xspec/xspec#47 -->
<xsl:variable name="wrap">
<xsl:sequence select="$nodes" />
</xsl:variable>
<xsl:sequence select="$wrap" />
</xsl:function>

</xsl:stylesheet>


Expand Down
58 changes: 37 additions & 21 deletions frameworks/xspec/src/compiler/generate-xspec-tests.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

<xsl:template match="x:description" mode="x:generate-tests">
<!-- The compiled stylesheet element. -->
<stylesheet version="{( @xslt-version, '2.0' )[1]}"
<stylesheet version="{( @xslt-version, 2.0 )[1]}"
exclude-result-prefixes="pkg impl">
<xsl:apply-templates select="." mode="x:copy-namespaces" />
<import href="{$stylesheet-uri}" />
Expand Down Expand Up @@ -208,7 +208,7 @@
</xsl:variable>
<xsl:choose>
<xsl:when test="$context">
<!-- Set up the $context variable -->
<!-- Set up the $impl:context variable -->
<xsl:apply-templates select="$context" mode="x:setup-context"/>
<!-- Switch to the context and call the template -->
<for-each select="$impl:context">
Expand Down Expand Up @@ -256,7 +256,7 @@
</apply-templates>
</xsl:when>
<xsl:when test="$context">
<!-- Set up the $context variable -->
<!-- Set up the $impl:context variable -->
<xsl:apply-templates select="$context" mode="x:setup-context"/>
<!-- Set up variables containing the parameter values -->
<xsl:apply-templates select="$context/x:param[1]" mode="x:compile"/>
Expand Down Expand Up @@ -307,11 +307,10 @@
<xsl:value-of select="normalize-space(x:label(.))"/>
</message>
<xsl:if test="not($pending-p)">
<xsl:variable name="version" as="xs:double"
<xsl:variable name="xslt-version" as="xs:decimal"
select="(ancestor-or-self::*[@xslt-version]/@xslt-version, 2.0)[1]" />
<xsl:apply-templates select="." mode="test:generate-variable-declarations">
<xsl:with-param name="var" select="'impl:expected'" />
</xsl:apply-templates>
<!-- Set up the $impl:expected variable -->
<xsl:apply-templates select="." mode="x:setup-expected" />
<xsl:choose>
<xsl:when test="@test">
<!-- This variable declaration could be moved from here (the
Expand All @@ -325,15 +324,10 @@
$x:result as if they were *children* of the context node.
Have to experiment a bit to see if that really is the case.
TODO: To remove. Use directly $x:result instead. See issue 14. -->
<when test="$x:result instance of node()+">
<!-- $impl:test-items-doc aims to create an implicit document node as described
in http://www.w3.org/TR/xslt20/#temporary-trees
So its "variable" element must not have @as or @select.
Do not use "document" or "copy-of" element: xspec/xspec#47 -->
<variable name="impl:test-items-doc">
<sequence select="$x:result" />
</variable>
<sequence select="$impl:test-items-doc treat as document-node()" />
<when test="exists($x:result)
and (every $impl:result-item in $x:result
satisfies test:wrappable-node($impl:result-item))">
<sequence select="test:wrap-nodes($x:result)" />
</when>
<otherwise>
<sequence select="$x:result" />
Expand All @@ -344,25 +338,32 @@
<choose>
<when test="count($impl:test-items) eq 1">
<for-each select="$impl:test-items">
<sequence select="{ @test }" version="{ $version }"/>
<sequence select="{ @test }" version="{ $xslt-version }"/>
</for-each>
</when>
<otherwise>
<sequence select="{ @test }" version="{ $version }"/>
<sequence select="{ @test }" version="{ $xslt-version }"/>
</otherwise>
</choose>
</variable>
<!-- TODO: A predicate should always return exactly one boolean, or
this is an error. See issue 5.-->
<variable name="impl:boolean-test" as="xs:boolean"
select="$impl:test-result instance of xs:boolean" />
<xsl:if test="@href or @select or (node() except x:label)">
<if test="$impl:boolean-test">
<message>
<text>WARNING: <xsl:value-of select="name(.)"/> has boolean @test (i.e. assertion) along with @href, @select or child node (i.e. comparison). Comparison factors will be ignored.</text>
</message>
</if>
</xsl:if>
<variable name="impl:successful" as="xs:boolean"
select="if ($impl:boolean-test) then $impl:test-result cast as xs:boolean
else test:deep-equal($impl:expected, $impl:test-result, {$version})" />
select="if ($impl:boolean-test) then boolean($impl:test-result)
else test:deep-equal($impl:expected, $impl:test-result, {$xslt-version})" />
</xsl:when>
<xsl:otherwise>
<variable name="impl:successful" as="xs:boolean"
select="test:deep-equal($impl:expected, $x:result, {$version})" />
select="test:deep-equal($impl:expected, $x:result, {$xslt-version})" />
</xsl:otherwise>
</xsl:choose>
<if test="not($impl:successful)">
Expand Down Expand Up @@ -438,6 +439,21 @@
</xsl:apply-templates>
</xsl:template>

<xsl:template match="x:expect" mode="x:setup-expected" as="element(xsl:variable)+">
<!-- Remove x:label from x:expect -->
<xsl:variable name="expect" as="element(x:expect)">
<xsl:copy>
<xsl:sequence select="@*" />
<xsl:sequence select="node() except x:label" />
</xsl:copy>
</xsl:variable>

<!-- Generate <xsl:variable name="impl:expected"> to represent the expected items -->
<xsl:apply-templates select="$expect" mode="test:generate-variable-declarations">
<xsl:with-param name="var" select="'impl:expected'" />
</xsl:apply-templates>
</xsl:template>

<xsl:template match="x:context | x:param" mode="x:report">
<xsl:element name="x:{local-name()}">
<xsl:apply-templates select="@*" mode="x:report" />
Expand Down
17 changes: 9 additions & 8 deletions frameworks/xspec/src/schemas/xspec.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ description =
common-attributes,
attribute stylesheet { xs:anyURI }?,
attribute query { xs:anyURI }?,
attribute xslt-version { xs:NMTOKEN }?,
attribute xslt-version { xs:decimal }?,
attribute query-at { xs:anyURI }?,
attribute version { xs:NMTOKEN }?,
attribute version { xs:decimal }?,
attribute preserve-space { xs:NMTOKENS }?,
attribute schematron { xs:anyURI }?,
(global-param | import | scenario | pending)+ }
Expand Down Expand Up @@ -187,15 +187,16 @@ as = attribute as { text }

selection = node-selection | value-selection

node-selection =
## The document URI (location) of the imported document.
attribute href { xs:anyURI }?,
node-selection = (
## The document URI (location) of the selected document.
attribute href { xs:anyURI }
| user-content
),
## The XPath expression to access the selected node.
attribute select { xpath }?,
user-content
attribute select { xpath }?

value-selection =
## The XPath expression to access the selected node.
## The XPath expression without definitive context.
attribute select { xpath }

xpath = text
Expand Down
21 changes: 21 additions & 0 deletions frameworks/xspec/xspec.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2008-2017 Jeni Tennison

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

0 comments on commit 3ec0b78

Please sign in to comment.