zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #15489
[Merge] lp:~zorba-coders/zorba/feature_fots_driver into lp:zorba
Sorin Marian Nasoi has proposed merging lp:~zorba-coders/zorba/feature_fots_driver into lp:zorba.
Commit message:
Added Zorba FOTS driver.
Requested reviews:
Zorba Coders (zorba-coders)
Related bugs:
Bug #918156 in Zorba: "fots driver for Zorba"
https://bugs.launchpad.net/zorba/+bug/918156
Bug #956460 in Zorba: "Zorba FOTS driver: assert-serialization bug"
https://bugs.launchpad.net/zorba/+bug/956460
Bug #973410 in Zorba: "Zorba FOTS driver: assert-deep-eq bug"
https://bugs.launchpad.net/zorba/+bug/973410
Bug #973412 in Zorba: "Zorba FOTS driver: assert-permutation bug"
https://bugs.launchpad.net/zorba/+bug/973412
Bug #973416 in Zorba: "Zorba FOTS driver: assert-assert bug"
https://bugs.launchpad.net/zorba/+bug/973416
Bug #973417 in Zorba: "Zorba FOTS driver: assert-serialization-error bug"
https://bugs.launchpad.net/zorba/+bug/973417
Bug #973434 in Zorba: "Zorba FOTS driver: assert-error bug"
https://bugs.launchpad.net/zorba/+bug/973434
Bug #1017389 in Zorba: "Zorba FOTS driver: improve statistics reporting"
https://bugs.launchpad.net/zorba/+bug/1017389
Bug #1052856 in Zorba: "URI resolvers in Zorba FOTS driver"
https://bugs.launchpad.net/zorba/+bug/1052856
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/feature_fots_driver/+merge/130563
Added Zorba FOTS driver.
--
https://code.launchpad.net/~zorba-coders/zorba/feature_fots_driver/+merge/130563
Your team Zorba Coders is requested to review the proposed merge of lp:~zorba-coders/zorba/feature_fots_driver into lp:zorba.
=== added directory 'test/fots_driver'
=== added file 'test/fots_driver/README.TXT'
--- test/fots_driver/README.TXT 1970-01-01 00:00:00 +0000
+++ test/fots_driver/README.TXT 2012-10-19 14:36:26 +0000
@@ -0,0 +1,26 @@
+Information about the W3C XQuery/XPath/XSLT 3.* Test Suite can be found here: http://dev.w3.org/2011/QT3-test-suite .
+
+In order to use the Zorba FOTS driver (written in XQuery) one has to follow these steps:
+
+0) Compile Zorba with the XQXQ external module.
+
+1) Download the FOTS testsuite from W3C
+ Since currently there is no official release, a simple "cvs get" will do:
+
+ $ export CVSROOT=":pserver:anonymous@xxxxxxxxxx:/sources/public"
+ $ cvs login
+ (Logging in to anonymous@xxxxxxxxxx)
+ CVS password: anonymous
+ $ cvs get 2011/QT3-test-suite
+
+3) run
+ ./zorba -f
+ -q ../../test/fots_driver/fots.xq
+
+and get a list of options you can pass to the FOTS driver in order to:
+ - list the available test sets in the FOTS (see function fots:list-test-sets)
+ - run all test cases in the test sets (see fots:run-fots functions)
+ - run a single test set if you are a module developer (see fots:run-test-set function)
+ - run a single test case (see fots:test function)
+ - run and reporting statistics (see reporting:run-and-report function)
+ - load a failures file and reporting statistics (see reporting:run-and-report function)
=== added file 'test/fots_driver/fots-check.xqy'
--- test/fots_driver/fots-check.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots-check.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,355 @@
+xquery version "3.0";
+
+module namespace check = "http://www.w3.org/2010/09/qt-fots-catalog/check";
+
+declare namespace err = "http://www.w3.org/2005/xqt-errors";
+import schema namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
+
+import module namespace ser = "http://www.w3.org/2010/09/qt-fots-catalog/serialize" at "serialize.xqy";
+
+declare namespace ann = "http://www.zorba-xquery.com/annotations";
+import module namespace xqxq = "http://www.zorba-xquery.com/modules/xqxq";
+import module namespace schema = "http://www.zorba-xquery.com/modules/schema";
+declare namespace features = "http://www.zorba-xquery.com/options/features";
+declare option features:enable "hof";
+
+(:~
+ : Errors namespace URI.
+:)
+declare variable $check:errNS as xs:string := "http://www.w3.org/2010/09/qt-fots-catalog/check";
+
+(:~
+ : xs:QName with namespace URI="http://www.w3.org/2010/09/qt-fots-catalog/check" and local name "check:errNA"
+:)
+declare variable $check:errNA as xs:QName := fn:QName($check:errNS, "check:errNA");
+
+(:~
+ : The serialization parameters for XML serialization.
+ :)
+declare %private variable $check:serParamXml :=
+ <output:serialization-parameters>
+ <output:method value="xml" />
+ <output:indent value="no" />
+ <output:omit-xml-declaration value="yes" />
+ </output:serialization-parameters>;
+
+declare %private %ann:sequential function check:res(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ let $test := local-name($expResult)
+ return switch($test)
+ case 'all-of'
+ return check:assert-all-of($result, $expResult)
+ case 'any-of'
+ return check:assert-any-of($result, $expResult)
+ case 'assert'
+ return check:assert($result, $expResult)
+ case 'assert-count'
+ return check:assert-count($result, $expResult)
+ case 'assert-deep-eq'
+ return check:assert-deep-eq($result, $expResult)
+ case 'assert-empty'
+ return check:assert-empty($result)
+ case 'assert-eq'
+ return check:assert-eq($result, $expResult)
+ case 'assert-false'
+ return check:assert-bool($result, $expResult, fn:false())
+ case 'assert-permutation'
+ return check:assert-permutation($result, $expResult)
+ case 'assert-xml'
+ return check:assert-xml($result, $expResult)
+ case 'assert-serialization-error'
+ return check:assert-serialization-error($result, $expResult)
+ case 'assert-string-value'
+ return check:assert-string-value($result, $expResult)
+ case 'assert-true'
+ return check:assert-bool($result, $expResult, fn:true())
+ case 'assert-type'
+ return check:assert-type($result, $expResult)
+ case 'error'
+ return concat('Expected Error [', $result/@code, ']')
+ default return error(
+ fn:QName('http://www.w3.org/2005/xqt-errors', 'FOTS9999'),
+ concat('Unknown assertion: "', $test, '"'))
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_any-of :)
+declare %ann:sequential function check:assert-any-of(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ let $results := for $tmp in $expResult/*
+ return empty(check:res($result, $tmp))
+ return
+ if (some $result in $results satisfies $result)
+ then ()
+ else concat("'any-of' assertion returned: ",
+ string-join(for $result in $results return fn:string($result),', '))
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_all-of :)
+declare %ann:sequential function check:assert-all-of(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ for $tmp in $expResult/*
+ return check:res($result, $tmp)
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert :)
+declare %ann:sequential function check:assert(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ try {
+ let $queryText := concat(
+ "xquery version '3.0';",
+ "declare namespace o = 'http://www.zorba-xquery.com/options/features';",
+ "declare option o:enable 'hof';",
+ "declare variable $result external; ",
+ xs:string($expResult)),
+ $queryKey := xqxq:prepare-main-module($queryText),
+ $queryKeyResult := xqxq:bind-variable($queryKey, xs:QName('result'), $result),
+ $queryResult := xqxq:evaluate($queryKey)
+ return if($queryResult) then ()
+ else concat('Assertion ''', $expResult, ''' failed.')
+ } catch * {
+ concat('Assertion ''',
+ $expResult,
+ ''' failed with: [',
+ $err:code,
+ '] ',
+ $err:description)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-count :)
+declare function check:assert-count(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ let $count := count($result),
+ $exp := xs:integer($expResult)
+ return if($count eq $exp) then ()
+ else concat('Expected ', $exp, ' items, found ', $count, '.')
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-deep-eq :)
+declare %ann:sequential function check:assert-deep-eq(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ try {
+ let $queryText := concat(
+ "xquery version '3.0';",
+ "declare namespace o = 'http://www.zorba-xquery.com/options/features';",
+ "declare option o:enable 'hof';",
+ "declare variable $x external;",
+ "let $y := (",fn:string(fn:data($expResult)),") return ",
+ "every $i in 1 to max((count($x),count($y))) satisfies deep-equal($x[$i],$y[$i])"),
+ $queryKey := xqxq:prepare-main-module($queryText),
+ $queryKeyResult := xqxq:bind-variable($queryKey, xs:QName('x'), $result),
+ $queryResult := xqxq:evaluate($queryKey)
+ return if($queryResult) then ()
+ else concat('Result is not deep-equal to ''', $expResult, '''.')
+ } catch * {
+ concat('Deep comparison to ''', $expResult, ''' failed with: [',
+ $err:code, '] ', $err:description)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-empty :)
+declare function check:assert-empty(
+ $result as item()*
+) as xs:string* {
+ if(empty($result)) then () else 'Result is not empty.'
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-eq :)
+declare %ann:sequential function check:assert-eq(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ try {
+ let $queryText := concat(
+ "xquery version '3.0';",
+ "declare namespace o = 'http://www.zorba-xquery.com/options/features';",
+ "declare option o:enable 'hof';",
+ "declare variable $x external;",
+ "declare function local:f($y) as xs:boolean {xs:string($x) eq xs:string(fn:data($y))};",
+ "let $f := local:f#1 return $f(", $expResult, ")"),
+ $queryKey := xqxq:prepare-main-module($queryText),
+ $queryKeyResult := xqxq:bind-variable($queryKey, xs:QName('x'), $result),
+ $queryResult := xqxq:evaluate($queryKey)
+ return
+ if($queryResult) then ()
+ else concat('Result doesn''t match expected item ''', xs:string($expResult), '''.')
+ } catch * {
+ concat('Comparison to ''', $expResult/text(), ''' failed with: [',
+ $err:code, '] ', $err:description)
+ }
+};
+
+(:
+ http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-true
+ http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-false
+:)
+declare function check:assert-bool(
+ $res as item()*,
+ $result as element(),
+ $exp as xs:boolean
+) {
+ if($res instance of xs:boolean and $res eq $exp) then ()
+ else fn:concat('Query doesn''t evaluate to ''', $exp, '''')
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-permutation :)
+declare %ann:sequential function check:assert-permutation(
+ $result as item()*,
+ $expResult as element()
+) {
+ try {
+ let $queryText := concat(
+ "xquery version '3.0';",
+ "declare namespace o = 'http://www.zorba-xquery.com/options/features';",
+ "declare option o:enable 'hof';",
+ "declare variable $x external;",
+ "let $y := (",fn:string(fn:data($expResult)),") return ",
+ (: if count(intersection(M1,M2)) = count(union(M1,M2)) = count(M1) then the sequences are identical :)
+ "(count(distinct-values($x[ . = $y])) = count(fn:distinct-values(($x, $y)))) = count(fn:distinct-values($x))"),
+ $queryKey := xqxq:prepare-main-module($queryText),
+ $queryKeyResult := xqxq:bind-variable($queryKey, xs:QName('x'), $result),
+ $queryResult := xqxq:evaluate($queryKey)
+ return if($queryResult) then ()
+ else concat('Result isn''t a permutation of ''', $expResult, '''.')
+ } catch * {
+ concat('Unordered comparison to ''', $expResult, ''' failed with: [',
+ $err:code, '] ', $err:description)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-xml :)
+declare function check:assert-xml(
+ $result as item()*,
+ $expResult as element()
+) {
+ try {
+ let $cmpRes as xs:string := if($result instance of node())
+ then fn:string-join(fn:serialize($result,
+ $check:serParamXml)
+ , ' ')
+ else fn:string($result)
+ return
+ if($cmpRes eq string($expResult))
+ then ()
+ else fn:concat('Serialized result ''', $cmpRes, ''' not equal to ''', $expResult, '''.')
+ } catch * {
+ concat('Serialized comparison to ''', $expResult, ''' failed with: [',
+ $err:code, '] ', $err:description)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-serialization-error :)
+declare function check:assert-serialization-error(
+ $result as item()*,
+ $expResult as element()
+) {
+ try {
+ let $cmpRes as xs:string := if($result instance of node())
+ then fn:string-join(fn:serialize($result,
+ $check:serParamXml)
+ , ' ')
+ else fn:string($result)
+ return
+ fn:concat('Expected serialization error but got result ''', $cmpRes, '''.')
+ } catch * {
+ check:error($err:code,
+ $err:description,
+ $expResult)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-string-value :)
+declare function check:assert-string-value(
+ $res as item()*,
+ $result as element()
+) as xs:string* {
+ try {
+ let $str := if (empty($result[@normalize-space="true"]))
+ then fn:string-join(for $r in $res return xs:string($r), " ")
+ else fn:normalize-space(fn:string-join(for $r in $res return xs:string($r), " ")),
+ $exp := if (empty($result[@normalize-space="true"]))
+ then xs:string($result)
+ else fn:normalize-space(xs:string($result))
+ return if($str eq $exp) then ()
+ else fn:concat('Expected ''', $exp, ''', found ''', $str, '''.')
+ } catch * {
+ fn:concat('String eq comparison to ', $result, ' failed with: [',
+ $err:code, '] ', $err:description)
+ }
+};
+
+(: http://dev.w3.org/2011/QT3-test-suite/catalog-schema.html#elem_assert-type :)
+declare function check:assert-type(
+ $result as item()*,
+ $expResult as element()
+) as xs:string* {
+ try {
+ let $typeResult := xs:string(schema:schema-type($result[1])),
+ $type := xs:string($expResult)
+ return if($type eq $typeResult) then ()
+ else concat('Result doesn''t have type ''', $type, '''.')
+ } catch * {
+ concat('Type check for ''', $result,
+ ''' failed with: [', $err:code, '] ', $err:description)
+ }
+};
+
+declare %ann:sequential function check:result(
+ $result as item()*,
+ $expResult as element()
+) as element()? {
+ let $err := check:res($result, $expResult)
+ return if(empty($err)) then () else
+ <out>
+ <result>{ser:serialize($result)}
+ </result>
+ <errors>{ser:serialize($err)}
+ </errors>
+ </out>
+};
+
+declare function check:error(
+ $code as xs:QName,
+ $error as xs:string,
+ $result as element()
+) as element()? {
+ let $err := check:err($code, $error, $result)
+ return if(empty($err)) then () else
+ <out>
+ <result>Error: {concat('[', $code, '] ', $error)}</result>
+ <errors>{$err}</errors>
+ </out>
+};
+
+declare %private function check:err(
+ $code as xs:QName,
+ $err as xs:string,
+ $result as element()
+) as xs:string* {
+ let $errors := $result/descendant-or-self::*:error
+ return
+ if(exists($errors[@code = "*"]))
+ then ()
+ else
+ if(fn:namespace-uri-from-QName($code) = 'http://www.w3.org/2005/xqt-errors' and
+ exists($errors[@code = fn:local-name-from-QName($code)]))
+ then ()
+ else if(exists($errors)) then (
+ concat('Wrong error code [', $code, '] (', $err, '), expected: [',
+ string-join($errors//@code, '], ['), ']')
+ ) else (
+ concat('Expected result, found error: [', $code, '] ', $err)
+ )
+};
\ No newline at end of file
=== added file 'test/fots_driver/fots-environment.xqy'
--- test/fots_driver/fots-environment.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots-environment.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,179 @@
+xquery version "3.0";
+
+module namespace env = "http://www.w3.org/2010/09/qt-fots-catalog/environment";
+
+declare namespace fots = "http://www.w3.org/2010/09/qt-fots-catalog";
+
+declare namespace ann = "http://www.zorba-xquery.com/annotations";
+import module namespace xqxq = "http://www.zorba-xquery.com/modules/xqxq";
+
+import module namespace file = "http://expath.org/ns/file";
+
+import module namespace util = "http://www.w3.org/2010/09/qt-fots-catalog/util"
+ at "fots-util.xqy";
+
+(: retrieves the environment node from a test-set or catalog given a environment name :)
+declare function env:get-environment (
+ $catalog,
+ $set,
+ $envName as xs:string
+) as element(fots:environment)? {
+ let $envTestSet := $set/test-set//environment[@name = $envName]
+ return
+ if (fn:empty($envTestSet))
+ then $catalog/catalog//environment[@name = $envName]
+ else $envTestSet
+};
+
+(:TODO If the test expression includes the string "(:%VARDECL%:)"
+ then the variable declaration should be added to replace this string;
+ if it does not include this string, the variable declaration can be added at the start. :)
+declare %ann:nondeterministic function env:add-var-decl(
+ $env as element(fots:environment)?,
+ $case as element(fots:test-case),
+ $path as xs:string?
+) as xs:string? {
+ fn:concat(env:var-decl-with-value($env, $case/*:environment),
+ env:var-decl-without-value($env, $case/*:environment, $path))
+};
+
+(: if defined, returns the string for setting the context item :)
+declare function env:set-context-item(
+ $env as element(fots:environment)?,
+ $relativePath as xs:string?
+) as xs:string? {
+ if(data($env/@name) = 'empty') then ()
+ else if (fn:exists($env/*:source[@role = "."])) then
+ string-join((concat('variable $contextItem := doc("',
+ concat( $relativePath,
+ file:directory-separator(),
+ fn:data($env/*:source[@role = "."]/@file)),
+ '");'),
+ 'xqxq:bind-context-item($queryID, $contextItem);'),"
")
+ else ()
+};
+
+(:~
+ : Returns the strings for variable binding in XQXQ.
+ :
+ : @param $env the environment of the catalog or the test-set (given with 'ref').
+ : @param $envCase the environment of the test-case.
+ : @param $relativePath the relative path for the environment.
+ : @return the queryKey after the variables were bound.
+ :)
+declare function env:set-variables(
+ $env as element(fots:environment)?,
+ $envCase,
+ $relativePath as xs:string?
+) as xs:string? {
+
+ let $srcNames := for $source in ($env/*:source, $envCase/*:source)
+ where fn:starts-with(fn:data($source/@role),"$")
+ return substring-after(fn:data($source/@role),"$"),
+ $srcValues := for $srcName in $srcNames
+ return concat('fn:doc("',
+ $relativePath,
+ file:directory-separator(),
+ for $source in ($env/*:source, $envCase/*:source)
+ where $source[@role = concat("$",$srcName)]
+ return data($source/@file),
+ '")')
+ return
+ string-join((for $srcName in $srcNames
+ let $index := index-of($srcNames, $srcName)
+ return
+ concat('xqxq:bind-variable( $queryID, xs:QName("', $srcName, '")',
+ ', ', $srcValues[$index], ');'),
+
+ for $param in ($env/*:param, $envCase/*:param)
+ let $select:= fn:data($param/@select)
+ let $varValue := if(starts-with($select, "'") and ends-with($select, "'")) then
+ concat($relativePath,
+ file:directory-separator(),
+ for $source in ($env/*:source, $envCase/*:source)
+ where $source[@uri = fn:translate(fn:data($param/@select), "'", "")]
+ return fn:data($source/@file))
+ else $select
+ let $varName := fn:data($param/@name)
+ return
+ concat('xqxq:bind-variable( $queryID, xs:QName("', fn:data($param/@name), '")',
+ ', "', $varValue, '");')
+ ), "
")
+};
+
+declare function env:var-decl-with-value(
+ $env as element(fots:environment)?,
+ $envCase
+) as xs:string? {
+ fn:string-join(
+ for $param in ($env/*:param, $envCase/*:param)
+ where fn:exists(fn:data($param/@select))
+ and not(starts-with(fn:data($param/@select),"'"))
+ and empty(fn:data($param[@declared="true"]))
+ return concat("declare variable $",
+ fn:data($param/@name),
+ " := ",
+ fn:data($param/@select),";")
+ ," ")
+};
+
+declare function env:var-decl-without-value(
+ $env as element(fots:environment)?,
+ $envCase,
+ $path as xs:string?
+) as xs:string? {
+ fn:string-join(
+ (for $param in ($env/*:param, $envCase/*:param)
+ where (fn:empty(fn:data($param/@select)) or
+ (fn:exists(fn:data($param/@select))
+ and starts-with(fn:data($param/@select),"'")))
+ and empty(fn:data($param[@declared="true"]))
+ return concat("declare variable $",
+ fn:data($param/@name),
+ " external;"),
+ for $source in ($env/*:source, $envCase/*:source)
+ where fn:starts-with(fn:data($source/@role),"$")
+ return concat("declare variable ",
+ fn:data($source/@role),
+ " external;"))
+ ," ")
+};
+
+(:~
+ : Adds the necessary declare namespace statements.
+ :
+ : @param $env the environment of the catalog or the test-set (given with 'ref').
+ : @param $envCase the environment of the test-case.
+ : @return the declare namespace statements.
+ :)
+declare function env:decl-namespaces(
+ $env as element(fots:environment)?,
+ $envCase
+) as xs:string? {
+ string-join(for $ns in ($env/*:namespace, $envCase/*:namespace)
+ where fn:not($ns[@prefix=""])
+ return concat('declare namespace ',
+ fn:data($ns/@prefix),
+ ' = "',
+ fn:data($ns/@uri),
+ '";')
+ ," ")
+};
+
+(:~
+ : Sets the declared default element namespace.
+ :
+ : @param $env the environment of the catalog or the test-set (given with 'ref').
+ : @param $envCase the environment of the test-case.
+ : @return the declare default element namespace.
+ :)
+declare function env:decl-def-elem-namespace(
+ $env,
+ $envCase
+) as xs:string? {
+ for $ns in ($env/*:namespace, $envCase/*:namespace)
+ where $ns[@prefix=""]
+ return concat('declare default element namespace "',
+ fn:data($ns/@uri),
+ '";')
+};
=== added file 'test/fots_driver/fots-reporting.xqy'
--- test/fots_driver/fots-reporting.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots-reporting.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,147 @@
+xquery version "3.0";
+
+module namespace reporting = "http://www.w3.org/2010/09/qt-fots-catalog/reporting";
+
+import module namespace file = "http://expath.org/ns/file";
+import module namespace fots = "http://www.w3.org/2010/09/qt-fots-catalog"
+ at 'fots.xqy';
+import module namespace util = "http://www.w3.org/2010/09/qt-fots-catalog/util"
+ at "fots-util.xqy";
+import schema namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
+
+declare namespace err ="http://www.w3.org/2005/xqt-errors";
+declare namespace ann = "http://www.zorba-xquery.com/annotations";
+
+declare default element namespace "http://www.w3.org/2010/09/qt-fots-catalog";
+
+declare %private variable $reporting:serParamXml :=
+ <output:serialization-parameters>
+ <output:method value="xml"/>
+ <output:indent value="yes"/>
+ </output:serialization-parameters>;
+
+(:~
+ : Loops through the test-sets, runs then and creates statistics.
+ : @param $pathFOTSCatalog path to the FOTS catalog file.
+ : @param $exceptedTestCases lists of test cases that are not run(empty string means all tests will be run).
+ : @param $exceptedTestSets lists of test sets that are not run(empty string means all tests will be run).
+ : @param $verbose is set to TRUE it will also output the actual failures.
+ : @return a report of tests run.
+ :)
+declare %ann:sequential function reporting:run-and-report(
+ $pathFOTSCatalog as xs:string,
+ $exceptedTestCases as xs:string*,
+ $exceptedTestSets as xs:string*,
+ $verbose as xs:boolean
+) {
+ variable $failures := fots:run-fots($pathFOTSCatalog,
+ fots:list-test-sets($pathFOTSCatalog, ''),
+ '',
+ $exceptedTestCases,
+ $exceptedTestSets,
+ '');
+
+ file:write("failures.xml", $failures, $reporting:serParamXml);
+
+ reporting:do-reporting($pathFOTSCatalog, $failures, $exceptedTestCases, $exceptedTestSets, $verbose)
+};
+
+(:~
+ : Loops through the test-sets, reads the report of the failures and creates statistics.
+ : @param $pathFOTSCatalog path to the FOTS catalog file.
+ : @param $pathFailures path to the FOTS failures.
+ : @param $exceptedTestCases lists of test cases that are not run(empty string means all tests will be run).
+ : @param $exceptedTestSets lists of test sets that are not run(empty string means all tests will be run).
+ : @param $verbose is set to TRUE it will also output the actual failures.
+ : @return a report of tests run.
+ :)
+declare %ann:nondeterministic function reporting:report(
+ $pathFOTSCatalog as xs:string,
+ $pathFailures as xs:string,
+ $exceptedTestCases as xs:string*,
+ $exceptedTestSets as xs:string*,
+ $verbose as xs:boolean
+) {
+ if(not(file:is-file($pathFailures))) then
+ {
+ fn:error("The file failures file was not found. Suggestion: use fots:run-fots to generate it or use reporting:run-and-report function.")
+ }
+ else
+ try
+ {
+ let $failures := fn:parse-xml(file:read-text($pathFailures))
+ return
+ reporting:do-reporting($pathFOTSCatalog, $failures, $exceptedTestCases, $exceptedTestSets, $verbose)
+ }
+ catch *
+ {
+ fn:error(fn:concat( "The file <",
+ $pathFailures,
+ "> does not have the correct structure."))
+ }
+};
+
+
+(:~
+ : Loops through the test-sets and creates statistics.
+ : @param $pathFOTSCatalog path to the FOTS catalog file.
+ : @param $failures the test reported by Zorba as failed.
+ : @param $exceptedTestCases lists of test cases that are not run(empty string means all tests will be run).
+ : @param $exceptedTestSets lists of test sets that are not run(empty string means all tests will be run).
+ : @param $verbose is set to TRUE it will also output the actual failures.
+ : @return a report of tests run.
+ :)
+declare %ann:nondeterministic %private function reporting:do-reporting(
+ $pathFOTSCatalog as xs:string,
+ $failures,
+ $exceptedTestCases,
+ $exceptedTestSets,
+ $verbose as xs:boolean) {
+ let $catalog := util:doc($pathFOTSCatalog, 'catalog.xml')
+ return
+ <report>
+ {
+ let $totalNoTests := fn:sum(for $testSetFile in $catalog//test-set
+ let $file := fn:data($testSetFile/@file),
+ $testSet := util:doc($pathFOTSCatalog, $file)
+ return fn:count($testSet//test-case)),
+ $totalFailures := fn:count($failures//test-case),
+ $totalNotRun := fn:sum( for $exeptedTS in $exceptedTestSets
+ return
+ for $testSetFile in $catalog//test-set
+ let $file := fn:data($testSetFile/@file),
+ $testSet := util:doc($pathFOTSCatalog, $file)
+ where (fn:data($testSet/test-set/@name) = $exeptedTS)
+ return fn:count($testSet//test-case),
+ count($exceptedTestCases))
+ return
+ <brief totalTests="{$totalNoTests}"
+ totalFailures="{$totalFailures}"
+ totalNotRun="{$totalNotRun}" />
+ }
+ { for $testSetFile in $catalog//test-set
+ let $file := fn:data($testSetFile/@file),
+ $testSet := util:doc($pathFOTSCatalog, $file),
+ $testSetName := fn:data($testSet/test-set/@name),
+ $totalNoTestCases := fn:count($testSet//test-case),
+ $totalFailures := for $testCase in $failures//test-case
+ where $testCase/test-set[@name = $testSetName]
+ order by fn:data($testCase/@name)
+ return $testCase
+ return
+ <test-set name="{$testSetName}"
+ file="{$file}"
+ noFailures="{fn:count($totalFailures)}"
+ noTestsCases="{$totalNoTestCases}"
+ percent="{fn:round((1 - (fn:count($totalFailures) div $totalNoTestCases))*100,2)}"
+ failedTestNames="{fn:string-join( for $failure in $totalFailures
+ order by fn:data($failure/@name)
+ return fn:data($failure/@name)
+ ,",")}">
+ {if ($verbose) then $totalFailures else ()}
+ </test-set>
+ }
+ <exceptedTestCases>{$exceptedTestCases}</exceptedTestCases>
+ <exceptedTestSets>{$exceptedTestSets}</exceptedTestSets>
+ </report>
+};
\ No newline at end of file
=== added file 'test/fots_driver/fots-util.xqy'
--- test/fots_driver/fots-util.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots-util.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,41 @@
+xquery version "3.0";
+
+module namespace util = "http://www.w3.org/2010/09/qt-fots-catalog/util";
+
+declare namespace ann = "http://www.zorba-xquery.com/annotations";
+
+import module namespace file = "http://expath.org/ns/file";
+
+(: retrieves a document using a path and a suffix supplied as xs:strings
+ and returns the corresponding document node :)
+declare %ann:nondeterministic function util:doc(
+ $path as xs:string,
+ $suffix as xs:string
+) as document-node()? {
+ fn:parse-xml(
+ file:read-text(
+ file:resolve-path(
+ concat( $path,
+ file:directory-separator(),
+ $suffix
+ )
+ )
+ )
+ )
+};
+
+(: retrieves a document using a path and a suffix supplied as xs:strings
+ and returns the content as text :)
+declare %ann:nondeterministic function util:doc-as-text(
+ $path as xs:string,
+ $suffix as xs:string
+) as xs:string {
+ file:read-text(
+ file:resolve-path(
+ concat( $path,
+ file:directory-separator(),
+ $suffix
+ )
+ )
+ )
+};
\ No newline at end of file
=== added file 'test/fots_driver/fots.xq'
--- test/fots_driver/fots.xq 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots.xq 2012-10-19 14:36:26 +0000
@@ -0,0 +1,130 @@
+xquery version "3.0";
+
+import module namespace fots = "http://www.w3.org/2010/09/qt-fots-catalog"
+ at 'fots.xqy';
+import module namespace reporting = "http://www.w3.org/2010/09/qt-fots-catalog/reporting"
+ at 'fots-reporting.xqy';
+
+declare default element namespace "http://www.w3.org/2010/09/qt-fots-catalog";
+
+declare variable $fotsPath as xs:string external := "";
+declare variable $mode as xs:string external := "";
+declare variable $testSetPrefixes external := "";
+declare variable $testCasePrefixes external := "";
+declare variable $pattern as xs:string external := "";
+declare variable $flags as xs:string external := "";
+declare variable $failuresFilePath as xs:string external := "";
+declare variable $verbose as xs:string external := "false";
+
+(:list of assertion types:)
+declare variable $assertType as xs:string external := "";
+
+declare function local:tokenize-comma-or-empty-string($input as xs:string) as xs:string*
+{
+ let $tokens := tokenize($input, ",")
+ return if (exists($tokens)) then $tokens else ""
+};
+
+declare function local:usage() as xs:string
+{
+ string-join((
+ "Usage examples:",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=list-test-sets",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=list-test-sets -e testSetPrefixes:=prod,app",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=list-test-cases -e testSetPrefixes:=prod-Literal",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=list-matching-test-cases -e pattern:=catch",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=run-test-sets -e testSetPrefixes:=prod-Literal",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=run-test-cases -e testSetPrefixes:=prod-Literal -e testCasePrefixes:=Literal",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=run-and-report",
+ "zorba -f -q /path/to/fots.xq -e fotsPath:=/path/to/w3c/dev/2011/QT3-test-suite/ -e mode:=run-and-report -e failuresFilePath:=failures.xml -e verbose:=true",
+ ""
+ ), "
")
+};
+
+(:~ The test in this list have bugs assigned already and should not be run :)
+variable $exceptedTestCases := (
+"context-item-1" (:see bug #867199 :)
+,"xqhof7", "xqhof13", "xqhof14" (:see bug #947051 :)
+,"FunctionCall-020" (:see bug #947064 :)
+,"group-013" (: already asked Matthias to fix the test :)
+,"generate-id-901", "generate-id-902" (:see bug #947130:)
+,"try-catch-function-call-3", "try-catch-function-call-4" (:see bug #:)
+,"fn-nilled-29"
+,"CastAsNamespaceSensitiveType-4", "CastAsNamespaceSensitiveType-5"
+,"instanceof131"
+);
+
+(:~ The test in this list have bugs assigned already and should not be run :)
+variable $exceptedTestSets := (
+"fn-matches.re", "misc-HigherOrderFunctions", "prod-NamedFunctionRef" (: these test-sets have a lot of seg faults :)
+,"app-Demos" (: have to implement an exception for the tests that are wrong to be reported as failing :)
+,"app-CatalogCheck"
+,"fn-subsequence", "misc-CombinedErrorCodes", "prod-SchemaImport"
+);
+
+switch ($mode)
+case "list-test-sets"
+ return string-join((fots:list-test-sets($fotsPath,
+ local:tokenize-comma-or-empty-string($testSetPrefixes)), ""),
+ "
")
+case "list-test-cases"
+ return string-join((fots:list-test-cases($fotsPath,
+ local:tokenize-comma-or-empty-string($testSetPrefixes)), ""),
+ "
")
+case "list-matching-test-cases"
+ return string-join((fots:list-matching-test-cases($fotsPath,
+ $pattern,
+ $flags), ""),
+ "
")
+case "run-test-sets"
+ return fots:run-fots( $fotsPath,
+ local:tokenize-comma-or-empty-string($testSetPrefixes),
+ '',
+ $exceptedTestCases,
+ $exceptedTestSets,
+ $assertType)
+case "run-test-cases"
+ return fots:run-fots( $fotsPath,
+ local:tokenize-comma-or-empty-string($testSetPrefixes),
+ local:tokenize-comma-or-empty-string($testCasePrefixes),
+ $exceptedTestCases,
+ $exceptedTestSets,
+ $assertType)
+case "run-and-report"
+ return reporting:run-and-report($fotsPath,
+ $exceptedTestCases,
+ $exceptedTestSets,
+ xs:boolean($verbose))
+case "report"
+ return reporting:report($fotsPath,
+ $failuresFilePath,
+ $exceptedTestCases,
+ $exceptedTestSets,
+ xs:boolean($verbose))
+default
+ return local:usage()
+
+(: example for running a single test case :)
+(:
+fots:test(
+ <test-case name="fn-absint1args-1">
+ <description>Test: absint1args-1 The "abs" function with the arguments set as follows: $arg = xs:int(lower bound) </description>
+ <created by="Carmelo Montanez" on="2004-12-13"/>
+ <environment ref="empty"/>
+ <test>fn:abs(xs:int("-2147483648"))</test>
+ <result>
+ <all-of>
+ <assert-eq>2147483648</assert-eq>
+ <assert-type>xs:integer</assert-type>
+ </all-of>
+ </result>
+ </test-case>
+ )
+:)
+
+(: example for running a test set for an external module :)
+(:
+fots:run-test-set('/home/spungi/Downloads/has-children.xml',
+ 'fn-has-children-001'
+ )
+:)
=== added file 'test/fots_driver/fots.xqy'
--- test/fots_driver/fots.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/fots.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,467 @@
+
+xquery version "3.0";
+
+(: global namespace of the test suite. :)
+module namespace fots = "http://www.w3.org/2010/09/qt-fots-catalog";
+
+declare default element namespace "http://www.w3.org/2010/09/qt-fots-catalog";
+
+declare namespace ann = "http://www.zorba-xquery.com/annotations";
+import module namespace xqxq = "http://www.zorba-xquery.com/modules/xqxq";
+
+declare namespace err = "http://www.w3.org/2005/xqt-errors";
+
+import module namespace file = "http://expath.org/ns/file";
+import module namespace functx = "http://www.functx.com/";
+
+import module namespace check = "http://www.w3.org/2010/09/qt-fots-catalog/check"
+ at "fots-check.xqy";
+
+import module namespace env = "http://www.w3.org/2010/09/qt-fots-catalog/environment"
+ at "fots-environment.xqy";
+
+import module namespace util = "http://www.w3.org/2010/09/qt-fots-catalog/util"
+ at "fots-util.xqy";
+
+declare %private variable $fots:hof as xs:string :=
+ string-join(("declare namespace op = 'http://www.zorba-xquery.com/options/features';",
+ "declare namespace f = 'http://www.zorba-xquery.com/features';",
+ "declare option op:enable 'f:hof';")
+ ,"
");
+
+(:~
+ : Loops through the FOTS catalog and returns all available test set names.
+ : @param $path path to the FOTS catalog file.
+ : @param $testSets a sequence of test set prefixes.
+ : @return available fots test-cases element names.
+ :)
+declare %ann:nondeterministic function fots:list-test-sets(
+ $path as xs:string,
+ $testSets as xs:string*
+) as xs:string* {
+ let $doc := util:doc($path, 'catalog.xml')
+ for $catalog in $testSets
+ for $testSet in $doc//test-set[starts-with(@name, $catalog)]
+ return fn:data($testSet/@name)
+};
+
+(:~
+ : Loops through the given test sets and returns the corresponding test cases.
+ : @param $path path to the FOTS catalog file.
+ : @param $testSets a sequence of test set prefixes.
+ : @return available fots test-cases element names.
+ :)
+declare %ann:nondeterministic function fots:list-test-cases(
+ $path as xs:string,
+ $testSets as xs:string*
+) as xs:string* {
+ let $doc := util:doc($path, 'catalog.xml')
+ for $testSet in $doc//test-set[starts-with(@name, $testSets)]
+ let $file := fn:data($testSet/@file),
+ $testSet := util:doc($path, $file)
+ return $testSet//test-case/@name/data(.)
+};
+
+(:~
+ : Loops through the FOTS catalog and returns all test cases that match given pattern using given flags.
+ : @param $path path to the FOTS catalog file.
+ : @param $pattern pattern.
+ : @param $flags flags.
+ : @return available fots test-cases matching given pattern and flags.
+ :)
+declare %ann:nondeterministic function fots:list-matching-test-cases(
+ $path as xs:string,
+ $pattern as xs:string,
+ $flags as xs:string?
+) as xs:string* {
+ let $catalog := util:doc($path, 'catalog.xml')
+ return
+ for $testSet in $catalog//test-set
+ let $file := fn:data($testSet/@file),
+ $testSet := util:doc($path, $file)
+ for $testCase in $testSet//test-case
+ where fn:matches(fots:get-test-case-text($testCase, $path), $pattern, $flags)
+ return
+ fn:concat("File: ", $path, file:directory-separator(), $file,
+ ", test name:", fn:data($testCase/@name),"
+")
+};
+
+(:~
+ : Loops throgh the test set and evaluates all test cases.
+ : @param $path path to the FOTS catalog file.
+ : @return an element containing all failed tests
+ :)
+declare %ann:sequential function fots:run-fots(
+ $path as xs:string
+) as element(fots:failures) {
+ fots:run-fots($path, '', '','','','')
+};
+
+(:~
+ : Loops throgh the test set and evaluates all test cases.
+ : @param $fotsPath path to the FOTS catalog file.
+ : @param $exceptedTestCases lists of test cases that should not be run(empty string means all tests will be run).
+ : @param $exceptedTestSets lists of test sets that should not be run(empty string means all tests will be run).
+ : @return an element containing all failed tests
+ :)
+declare %ann:sequential function fots:run-fots(
+ $fotsPath as xs:string,
+ $exceptedTestCases as xs:string*,
+ $exceptedTestSets as xs:string*
+) as element(fots:failures) {
+ fots:run-fots($fotsPath,
+ fots:list-test-sets($fotsPath, ""),
+ '',
+ $exceptedTestCases,
+ $exceptedTestSets,
+ '')
+};
+
+declare %private function fots:list-assertions(
+ $case as element(fots:test-case)) as xs:string*
+{
+ fn:distinct-values(for $assert in $case/result/*
+ return fn:local-name-from-QName(fn:node-name($assert)))
+};
+
+(:~
+ : Loops through the test sets and evaluates all test cases that have a certain assert-type.
+ : This is useful for testing the implementation of a certain assert type.
+ : @param $path path to the FOTS catalog file.
+ : @param $category name the catalog to use (empty string means all).
+ : @param $prefix prefix of test-cases to use (empty string means all).
+ : @param $exceptedTestCases lists of test cases that should not be run(empty string means all tests will be run).
+ : @param $exceptedTestSets lists of test sets that should not be run(empty string means all tests will be run).
+ : @param $assert lists of tests that contain a certain assert-type(empty string means all tests will be run).
+ : @return an element containing all failed tests
+ :)
+declare %ann:sequential function fots:run-fots(
+ $path as xs:string,
+ $testSetPrefixes as xs:string*,
+ $testCasePrefixes as xs:string*,
+ $exceptedTestCases as xs:string*,
+ $exceptedTestSets as xs:string*,
+ $assert as xs:string*
+) as element(fots:failures) {
+ <failures>{
+ let $catalog := util:doc($path, 'catalog.xml'),
+ $catalogTestSets := $catalog//test-set/@name,
+ $testSets := if ($testSetPrefixes = '') then functx:value-except($catalogTestSets, $exceptedTestSets)
+ else functx:value-except(functx:value-intersect($testSetPrefixes, $catalogTestSets), $exceptedTestSets)
+ for $testSetName in $testSets
+ let $file := fn:data($catalog//test-set[@name=$testSetName]/@file),
+ $testSetDoc := util:doc($path, $file),
+ $tsDependencies := fots:dependencies-present($testSetDoc/test-set/dependency)
+ for $testCase in $testSetDoc//test-case
+ let $envName := fn:data($testCase/environment/@ref),
+ $envTestSet := $testSetDoc/test-set//environment[@name = $envName],
+ $pathTestSet := fots:path($path, $file),
+ $envCatalog := $catalog/catalog//environment[@name = $envName],
+ $pathCatalog := $path,
+ $tcDependencies := fots:dependencies-present($testCase/dependency),
+ $shouldRun := if ($testCasePrefixes = '') then functx:value-except(xs:string(fn:data($testCase/@name)), $exceptedTestCases)
+ else functx:value-except(functx:value-intersect(fn:data($testCase/@name), $testCasePrefixes), $exceptedTestCases),
+ (:true if the tests-case has an assertion type that is requested :)
+ $hasReqAssert := (($assert = '') or
+ fn:exists(functx:value-intersect(fots:list-assertions($testCase),$assert)))
+ where $shouldRun and $hasReqAssert and $tcDependencies
+ order by fn:data($testCase/@name)
+ where $tsDependencies
+ order by $testSetName
+ return
+ if(fn:empty($envTestSet))
+ then fots:test( $testCase,
+ $envCatalog,
+ $path,
+ ($testSetDoc/test-set/dependency, $testCase/dependency),
+ $testSetName,
+ $pathTestSet)
+ else if (fn:exists($envTestSet))
+ then fots:test( $testCase,
+ $envTestSet,
+ $pathTestSet,
+ ($testSetDoc/test-set/dependency, $testCase/dependency),
+ $testSetName,
+ $pathTestSet)
+ else ()
+
+ }</failures>
+};
+
+(:~
+ : Loops through the test set and evaluates all test cases.
+ : @param $path path to the test set file.
+ : @param $prefix prefix of test-cases to use (empty string means all).
+ : @return an element containing all failed tests
+ :)
+declare %ann:sequential function fots:run-test-set(
+ $path as xs:string,
+ $prefixes as xs:string*
+) as element(fots:failures) {
+ <failures>{
+ let $testSet := util:doc($path, '')/test-set
+ for $prefix in $prefixes
+ for $testCase in $testSet//test-case[starts-with(@name, $prefix)]
+ let $envName := fn:data($testCase/environment/@ref),
+ $env := if(empty($envName)) then ()
+ else env:get-environment((), $testSet, $envName),
+ $testSetDep := $testSet/dependency,
+ $testSetName := fn:data($testSet/@name)
+ return fots:test( $testCase,
+ $env,
+ "",
+ $testSetDep,
+ $testSetName,
+ $path)
+ }</failures>
+};
+
+
+(:~
+ : Helper function: Runs a single test.
+ :
+ : @param $case test-case element
+ : @return empty sequence on success, the failed
+ : test-case element with additional information otherwise
+ :)
+declare %ann:sequential function fots:test(
+ $case as element(fots:test-case)
+) as element(fots:test-case)? {
+ fots:test($case, (), (), (), (),())
+};
+
+declare %private function fots:create-XQXQ-query(
+ $queryText as xs:string,
+ $case as element(fots:test-case),
+ $env as element(fots:environment)?,
+ $pathEnv as xs:string?,
+ $pathTestSet as xs:string) as xs:string
+{
+ (: uncomment the call to fots:resolver after bug #1052962 :)
+ let $resolver as xs:string? := fots:resolver($case, $env, $pathEnv, $pathTestSet)
+ return
+ string-join(("import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';",
+ if (exists($resolver))
+ then ($resolver,
+ concat("variable $queryID := xqxq:prepare-main-module('", "
", fn:replace($queryText,"'","''"), "',", "
",
+ "resolver:url-resolver#2, ());"))
+ else concat("variable $queryID := xqxq:prepare-main-module('", fn:replace($queryText,"'","''"), "');"),
+ env:set-context-item($env, $pathEnv),
+ env:set-variables($env, $case/environment, $pathEnv),
+ "xqxq:evaluate($queryID)"
+ ),
+ "
")
+};
+
+declare %private function fots:resolver(
+ $case as element(fots:test-case),
+ $env as element(fots:environment)?,
+ $pathEnv as xs:string?,
+ $pathTestSet as xs:string) as xs:string?
+{
+ let $envSchema := $env/*:schema,
+ $tcSchema := $case/*:environment/*:schema,
+ $schemas := ($envSchema, $tcSchema),
+ $modules := $case/*:module
+ return
+ if (empty($schemas) and empty($modules)) then ()
+ else
+ string-join(("declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver';",
+ $fots:hof,
+ "declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string) {",
+ "switch($entity)",
+ if (exists($schemas)) then
+ string-join(("case 'schema'",
+ " return switch($namespace)",
+ (for $schema in $envSchema
+ return concat(" case '",
+ data($schema/@uri),
+ "' return doc('",
+ concat($pathEnv, file:directory-separator(), data($schema/@file)),
+ "')"),
+ for $schema in $tcSchema
+ return concat(" case '",
+ data($schema/@uri),
+ "' return doc('",
+ concat($pathTestSet, file:directory-separator(), data($schema/@file)),
+ "')")),
+ " default return ()")
+ ,"
")
+ else (),
+ if (exists($modules)) then
+ string-join(("case 'module'",
+ " return switch($namespace)",
+ for $module in $modules
+ return concat(" case '",
+ data($module/@uri),
+ "' return doc('",
+ concat($pathTestSet, file:directory-separator(), data($module/@file)),
+ "')"),
+ " default return ()")
+ ,"
")
+ else ()
+ , "default return ()","};"),
+ "
")
+};
+
+declare %private %ann:sequential function fots:xqxq-invoke(
+ $xqxqQueryText as xs:string,
+ $case as element(fots:test-case))
+{
+ try {
+ let $queryKey := xqxq:prepare-main-module($xqxqQueryText),
+ $queryResult := xqxq:evaluate-sequential($queryKey)
+ return check:result($queryResult, $case/*:result/*)
+ } catch * {
+ check:error($err:code,
+ $err:description,
+ $case/*:result/*)
+ }
+};
+
+(:~
+ : Helper function for retrieving the query text.
+ :
+ : @param $case test-case element
+ : @param $path the path of the test-set
+ : @return the query text
+ :)
+declare %private %ann:nondeterministic function fots:get-test-case-text(
+ $case as element(fots:test-case),
+ $path as xs:string?) as xs:string
+{
+ if(exists($case/*:test/@file)) then
+ util:doc-as-text($path, data($case/*:test/@file))
+ else xs:string(fn:data($case/*:test))
+};
+
+(:~
+ : Runs a single test.
+ :
+ : @param $case test-case element
+ : @param $env the environment
+ : @param $pathEnv the relative path used to calculate the full path for the
+ : different children of the environment that have a "file" attribute
+ : @param $testSetName the name of the test-set
+ : @param $pathTestSet the path to the test-set
+ : @return empty sequence on success, the failed
+ : test-case element with additional information otherwise
+ :)
+declare %ann:sequential function fots:test(
+ $case as element(fots:test-case),
+ $env as element(fots:environment)?,
+ $pathEnv as xs:string?,
+ $deps as element(fots:dependency)*,
+ $testSetName as xs:string?,
+ $pathTestSet as xs:string
+) as element(fots:test-case)? {
+ let $queryName := trace(fn:data($case/@name)," processing test case :"),
+ $queryText as xs:string := fn:string-join(
+ (fots:add-xquery-30(($deps, $case//dependency)),
+ env:decl-def-elem-namespace($env, $case/environment),
+ (:env:decl-namespaces($env, $case/environment),:)
+ fots:enable-HOF-feature($deps),
+ env:add-var-decl($env, $case, $pathEnv),
+ fots:get-test-case-text($case, $pathTestSet)
+ ),"
"),
+ $xqxqQueryText as xs:string := fots:create-XQXQ-query($queryText, $case, $env, $pathEnv, $pathTestSet),
+ (:Tests that need XML 1.1 are marked as failing:)
+ $result := if (fn:data($case/*:dependency[@type="xml-version"]/@value) = "1.1") then
+ "XML version 1.1 not supported."
+ else
+ fots:xqxq-invoke($xqxqQueryText, $case)
+
+ return if(fn:empty($result)) then ()
+ else fots:wrong($case, $result, $xqxqQueryText, $testSetName, $env)
+};
+
+(: gives feedback on an erroneous query :)
+declare %private %ann:sequential function fots:wrong(
+ $test as element(fots:test-case),
+ $result as item()*,
+ $zorbaQuery as xs:string,
+ $testSetName as xs:string?,
+ $env as element(fots:environment)?
+) as element(fots:test-case)? {
+ let $tmp := $test,
+ $testName := trace(fn:data($test/@name),"failing test-case-name:")
+ return {
+ insert node
+ <wrong>
+ <query>
+ { $zorbaQuery }
+ </query>
+ { $env }
+ {$result}
+ </wrong>
+ as last into $tmp;
+
+ insert node
+ <test-set name="{trace($testSetName," test-set-name :")}" />
+ as first into $tmp;
+
+ delete node $tmp/description;
+
+ delete nodes $tmp/descendant::comment();
+
+ $tmp
+ }
+};
+
+(: retrieves the path given 2 different components
+ example: fots:path('/home','user/file.ext') returns '/home/user' :)
+declare %private function fots:path(
+ $path as xs:string,
+ $suffix as xs:string
+) as xs:string {
+ concat($path,
+ file:directory-separator(),
+ fn:substring-before($suffix,
+ concat(file:directory-separator(),file:base-name($suffix)))
+ )
+};
+
+declare %private function fots:dependencies-present(
+ $deps as element(fots:dependency)*
+) as xs:boolean {
+ let $dependencies := string-join(distinct-values(for $dep in $deps
+ where $dep[@type="spec"]
+ return data($dep/@value)),"")
+ return
+ if (contains($dependencies,"XT30")) then fn:false()
+ else if(contains($dependencies,"XP30")
+ and not(contains($dependencies,"XQ30") or contains($dependencies,"XQ10"))) then fn:false()
+ else fn:true()
+};
+
+declare %private function fots:add-xquery-30(
+ $deps as element(fots:dependency)*
+) as xs:string? {
+ let $dependencies := string-join(distinct-values( for $dep in $deps
+ where $dep[@type="spec"]
+ return data($dep/@value)),"")
+ return
+ if (contains($dependencies,"XQ30"))
+ then "xquery version '3.0';"
+ else ()
+};
+
+(:~
+ : If there is a dependency on XQuery 3.0 return the strings for enabling the HOF feature.
+ :
+ : @param $deps the dependencies of the test set and test case
+ : @param $case test-case element
+ : @param $env the environment
+ : @return if necessary the strings for enabling the HOF feature
+ :)
+declare %private function fots:enable-HOF-feature(
+ $deps as element(fots:dependency)*
+) as xs:string? {
+ let $dependencies := string-join(distinct-values( for $dep in $deps
+ where $dep[@type="spec"]
+ return data($dep/@value)),"")
+ return
+ if (contains($dependencies,"XQ30"))
+ then $fots:hof else ()
+};
=== added file 'test/fots_driver/serialize.xqy'
--- test/fots_driver/serialize.xqy 1970-01-01 00:00:00 +0000
+++ test/fots_driver/serialize.xqy 2012-10-19 14:36:26 +0000
@@ -0,0 +1,39 @@
+xquery version "3.0";
+
+module namespace ser = "http://www.w3.org/2010/09/qt-fots-catalog/serialize";
+
+declare function ser:serialize(
+ $seq as item()*
+) as xs:string {
+ fn:concat('(', fn:string-join(
+ (for $it in $seq
+ return ser:item($it))
+ , ', '), ')')
+};
+
+declare %private function ser:item(
+ $it as item()
+) as xs:string {
+ typeswitch($it)
+ case attribute()
+ return fn:concat(fn:name($it), '="', $it, '"')
+ case node()
+ return fn:serialize($it)
+ case function(*)
+ return ser:func($it)
+ case xs:untypedAtomic
+ return fn:concat('"', fn:replace($it, '"', '""'), '"')
+ case xs:string
+ return fn:concat('"', fn:replace($it, '"', '""'), '"')
+ default
+ return xs:string($it)
+};
+
+declare %private function ser:func(
+ $func as function(*)
+) as xs:string {
+ let $arity := fn:function-arity($func),
+ $name := if(fn:exists(fn:function-name($func)))
+ then fn:function-name($func) else '*function*'
+ return fn:concat($name, '#', $arity)
+};
\ No newline at end of file
Follow ups