Sorin Marian Nasoi has proposed merging lp:~zorba-coders/zorba/feature_fots 
into lp:zorba.

Requested reviews:
  Zorba Coders (zorba-coders)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/feature_fots/+merge/117579

Added Zorba FOTS driver.
-- 
https://code.launchpad.net/~zorba-coders/zorba/feature_fots/+merge/117579
Your team Zorba Coders is requested to review the proposed merge of 
lp:~zorba-coders/zorba/feature_fots 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-08-01 08:12:20 +0000
@@ -0,0 +1,29 @@
+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:anonym...@dev.w3.org:/sources/public"
+      $ cvs login
+        (Logging in to anonym...@dev.w3.org)
+        CVS password: anonymous
+      $ cvs get 2011/QT3-test-suite
+
+2)  Check out the examples in the ZORBA_FOLDER/test/fots_driver/fots.xq for:
+    - listing the available test sets in the FOTS (see function fots:list-test-sets)
+    - running all test cases in the test sets (see fots:run-fots functions)
+    - running a single test set if you are a module developer (see fots:run-test-set function)
+    - running a single test case (see fots:test function)
+    - running and reporting statistics (see reporting:run-and-report function)
+    - loading a failures file and reporting statistics (see reporting:run-and-report function)
+
+3)  run 
+    ./zorba -f 
+            -q ../../test/fots_driver/fots.xq 
+            -e fotsPath:="/home/spungi/work/zorba/w3c_repo/2011/QT3-test-suite" 
+            -o failures.xml 
+            --indent

=== 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-08-01 08:12:20 +0000
@@ -0,0 +1,337 @@
+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");
+
+declare %private function check:is-value-in-sequence
+  ( $value  as xs:anyAtomicType?,
+    $seq    as xs:anyAtomicType*) as xs:boolean {
+   $value = $seq
+ } ;
+
+(:~
+ : 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
+        for $tmp in $expResult/*
+        return check:res($result, $tmp)
+    case 'any-of'
+      return
+      let $results := for $tmp in $expResult/* 
+                      return empty(check:res($result, $tmp))
+      return 
+      if (check:is-value-in-sequence(fn:true(), (for $result in $results return $result)))
+      then ()
+      else concat("'any-of' assertion returned: ", 
+                  string-join(for $result in $results return fn:string($result),', ')) 
+    case 'assert'
+      return check:assert($result, $expResult)
+    case 'assert-count'
+      return
+        let $count := count($result),
+            $exp   := xs:integer($expResult)
+        return if($count eq $exp) then ()
+          else concat('Expected ', $exp, ' items, found ', $count, '.')
+    case 'assert-deep-eq'
+      return check:assert-deep-eq($result, $expResult)
+    case 'assert-empty'
+      return if(empty($result)) then () else 'Result is not empty.'
+    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 function check:any-of(
+  $res    as item()*,
+  $result as element()
+) as xs:string* {
+  fn:error($check:errNA, "Assertion type 'any-of' not implemented")
+};
+
+(:  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-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-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 := fn:string-join(for $r in $res return xs:string($r), " "),
+        $exp := 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-08-01 08:12:20 +0000
@@ -0,0 +1,133 @@
+xquery version "3.0";
+
+module namespace env = "http://www.w3.org/2010/09/qt-fots-catalog/environment";;
+
+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";
+
+declare function env:var-decl-with-value(
+  $env,
+  $envCase
+) as xs:string? {
+  fn:string-join(
+                  for $param in ($env/*:param, $envCase/*:param)
+                  where fn:exists(fn:data($param/@select))
+                  return concat("declare variable $",
+                                 fn:data($param/@name),
+                                " := ",
+                                fn:data($param/@select),";")
+                  ," ")
+};
+
+declare function env:var-decl-without-value(
+  $env,
+  $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))
+                  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;"))
+                  ," ")
+};
+
+(:~
+ : binds the variables that were added with attribute declared="true".
+ :
+ : @param $queryKey the query key.
+ : @param $env the environment of the catalog or the test-set (given with 'ref').
+ : @param $envCase the environment of the test-case.
+ : @return the queryKey after the variables were bound.
+ :)
+declare %ann:sequential function env:set-variables(
+  $queryKey     as xs:anyURI,
+  $env,
+  $envCase,
+  $relativePath as xs:string?
+) {
+  variable $select  := for $param in ($env/*:param, $envCase/*:param)
+                       where fn:not(fn:exists($param[@declared="false"]))
+                       return fn:translate(fn:data($param/@select), "'", ""),
+           $name    := for $param in ($env/*:param, $envCase/*:param)
+                       where fn:not(fn:exists($param[@declared="false"]))
+                       return fn:data($param/@name),
+           $suffix  := for $source in ($env/*:source, $envCase/*:source)
+                       where $source[@file = $select]
+                       return data($source/@uri),
+                       
+           $doc := concat($relativePath,
+                          file:directory-separator(),
+                          $suffix);
+  if(fn:exists($name)) then
+    xqxq:bind-variable( $queryKey,
+                        fn:QName("", $name),
+                        $doc);
+  else ();
+  
+
+  variable $varNames := for $source in ($env/*:source, $envCase/*:source)
+                        where fn:starts-with(fn:data($source/@role),"$")
+                        return substring-after(fn:data($source/@role),"$");
+  if(fn:exists($varNames)) then
+    for $varName in $varNames
+    let $xml := util:doc($relativePath,
+                         for $source in ($env/*:source, $envCase/*:source)
+                         where $source[@role = concat("$",$varName)]
+                         return data($source/@file))
+    return
+      xqxq:bind-variable( $queryKey,
+                          fn:QName("", $varName),
+                          $xml);
+  else ();
+};
+
+(:~
+ : 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,
+  $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),
+                '";')
+};
\ No newline at end of file

=== 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-08-01 08:12:20 +0000
@@ -0,0 +1,107 @@
+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";
+
+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";;
+
+(:~
+ : Loops through the test-sets, runs then and creates statistics.
+ : @param $pathFOTSCatalog path to the FOTS catalog file.
+ : @param $except lists of tests that should not be 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,
+  $except           as xs:string*,
+  $verbose          as xs:boolean
+) {
+  variable $failures := fots:run-fots($pathFOTSCatalog,
+                                      fots:list-test-sets($pathFOTSCatalog, ""),
+                                      "",
+                                      $except);
+  
+  reporting:do-reporting($pathFOTSCatalog, $failures, $except, $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 $except lists of tests that should not be 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,
+  $except           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, $except, $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 $except lists of tests that are not 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,
+  $except,
+  $verbose          as xs:boolean
+) {
+  <report>{
+    let $catalog := util:doc($pathFOTSCatalog, 'catalog.xml')
+    return
+    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]
+                          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 return fn:data($failure/@name),",")}">
+   {if ($verbose) then $totalFailures else ()}
+    </test-set>
+   }
+   <except>{$except}</except>
+   </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-08-01 08:12:20 +0000
@@ -0,0 +1,25 @@
+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 correponding 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
+        )
+      )
+    )
+  )
+};
\ 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-08-01 08:12:20 +0000
@@ -0,0 +1,94 @@
+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;
+
+(:~  The test in this list have bugs assigned already and should not be run :)
+variable $tests := (
+"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 #:)
+);
+
+(: 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 list-matching-test-cases function :)
+(:
+fots:list-matching-test-cases("/home/spungi/work/zorba/w3c_repo/2011/QT3-test-suite",
+                              "!",
+                              "") 
+:)
+
+(: List all available test-sets in the FOTS
+  app, fn, map, math, misc, op, prod, xs    :)
+(:
+  fots:list-test-sets(
+    $fotsPath,
+    ""
+  )
+:)
+
+(: example for running a single test set from the FOTS:)
+(:
+  fots:run-fots($fotsPath,
+              'fn-abs',                                   (:  the test-sets   :)
+              'K2-ABSFunc-35',                            (:  the test-cases  :)
+              ())
+:)
+
+(: example for running a test set for an external module :)
+(:
+fots:run-test-set('/home/spungi/Downloads/has-children.xml',
+                  'fn-has-children-001'
+                  )
+:)
+
+(: example for running the FOTS testsuite :)
+(:
+    fots:run-fots($fotsPath,
+              fots:list-test-sets($fotsPath, ""),
+              '',
+              $tests
+             )
+:)
+
+(: example for running the FOTS testsuite and reporting statistics :)
+
+  reporting:run-and-report( $fotsPath,
+                            $tests,
+                            fn:false()
+                           )
+
+
+(: example for loading a failures file and reporting statistics :)
+(:
+  reporting:report( $fotsPath,
+                    "/home/spungi/work/zorba/repo/feature_fots/build_release/bin/failures.xml",
+                    $tests,
+                    fn:false()
+                   )
+:)
\ No newline at end of file

=== 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-08-01 08:12:20 +0000
@@ -0,0 +1,379 @@
+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";
+
+(:~
+ : Loops through the FOTS catalog and returns all available test set names.
+ : @param $path path to the FOTS catalog file.
+ : @return available fots test-cases element names.
+ :)
+declare %ann:nondeterministic function fots:list-test-sets(
+  $path     as xs:string,
+  $catalogs as xs:string*
+) as xs:string* {
+  let $doc := util:doc($path, 'catalog.xml'),
+      $env := $doc//environment
+  return
+  for $catalog in $catalogs 
+    for $testSet in $doc//test-set[starts-with(@name, $catalog)]
+    return
+     fn:data($testSet/@name)
+};
+
+(:~
+ : 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(fn:data($testCase/*:test), $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 $except   lists of tests 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,
+  $except     as xs:string*
+) as element(fots:failures) {
+  fots:run-fots($fotsPath,
+                fots:list-test-sets($fotsPath, ""),
+                '',
+                $except)
+};
+
+(:~
+ : Loops through the test sets and evaluates all test cases.
+ : @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 $except   lists of tests 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(
+  $path       as xs:string,
+  $categories as xs:string*,
+  $prefixes   as xs:string*,
+  $except     as xs:string*
+) as element(fots:failures) {
+  <failures>{
+    let $catalog := util:doc($path, 'catalog.xml')
+    for $category in $categories
+      for $testSet in $catalog//test-set
+        let $file := fn:data($testSet/@file),
+            $testSetDoc := util:doc($path, $file),
+            $testSetName := fn:data($testSet/@name)
+      where $testSetName = $category
+        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,
+            $dep := ($testSetDoc/test-set/dependency, $testCase/dependency),
+            $runQuery := fots:check-should-run-test($dep),
+            $shouldRun  := (($prefixes eq xs:string('')) or fn:exists(functx:value-intersect($prefixes,xs:string(fn:data($testCase/@name))))),
+            $isExcepted := fn:exists(functx:value-intersect($except,  xs:string(fn:data($testCase/@name))))
+        where $shouldRun and fn:not($isExcepted)
+        (:TO DO fix this:) 
+              and not($testSetName = "fn-matches.re")
+              and not($testSetName = "misc-HigherOrderFunctions")
+              and not($testSetName = "prod-NamedFunctionRef")
+        order by fn:data($testCase/@name)
+    return
+      if(fn:empty($envTestSet)
+          and $runQuery
+          and fn:not($isExcepted))
+      then fots:test( $testCase,
+                      $envCatalog,
+                      $path,
+                      $dep,
+                      $testSetName)
+      else if (fn:exists($envTestSet)
+                and $runQuery
+                and fn:not($isExcepted))
+      then fots:test( $testCase,
+                      $envTestSet,
+                      $pathTestSet,
+                      $dep,
+                      $testSetName)
+      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 fots:get-environment((), $testSet, $envName),
+        $testSetDep := $testSet/dependency,
+        $testSetName := fn:data($testSet/@name)
+    return fots:test( $testCase, 
+                      $env,
+                      "",
+                      $testSetDep,
+                      $testSetName)
+  }</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 %ann:sequential function fots:xqxq-invoke(
+  $queryText  as xs:string,
+  $case       as element(fots:test-case),
+  $env        as element(fots:environment)?,
+  $path       as xs:string?)
+{
+  try {
+    let $queryKey := xqxq:prepare-main-module($queryText),
+        $queryKeyResult := fots:set-context-item($queryKey, $env, $path),
+        $queryKeyResult1 := env:set-variables($queryKey, $env, $case/environment, $path),
+        $queryResult := xqxq:evaluate($queryKey)
+    return check:result($queryResult, $case/*:result/*)
+  } catch * {
+    check:error($err:code,
+                $err:description,
+                $case/*:result/*)
+  }
+};
+  
+(:~
+ : Runs a single test.
+ :
+ : @param $case test-case element
+ : @param $env the environment
+ : @param $path 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
+ : @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)?,
+  $path as xs:string?,
+  $deps as element(fots:dependency)*,
+  $testSetName as xs:string?
+) as element(fots:test-case)? {
+  let $queryName := fn:data($case/@name),
+      $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, $case//dependency)),
+                                           fots:add-var-decl($env, $case, $path),
+                                           xs:string(fn:data($case/*:test))
+                                           )," "),
+      (: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($queryText, $case, $env, $path)
+  return if(fn:empty($result)) then ()
+    else fots:wrong($case, $result, $queryText, $testSetName)
+};
+
+(: 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?
+) 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>
+        {$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)))
+        )
+};
+
+(:  retrieves the environment node from a test-set or catalog given a environment name  :)
+declare %private function fots: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
+};
+
+(:  if defined, applies the context item to the $query-key  :)
+declare %private %ann:sequential function fots:set-context-item(
+  $queryKey     as xs:anyURI,
+  $env          as element(fots:environment)?,
+  $relativePath as xs:string?
+) {
+  try {
+    if(data($env/@name) = 'empty')
+    then $queryKey
+    else
+    {
+      (: Set context item if this exists :)
+      if (fn:exists($env/*:source[@role = "."])) then
+      {
+        variable $xml := util:doc($relativePath, fn:data($env/*:source/@file));
+        xqxq:bind-context-item($queryKey, $xml);
+      }
+      else ();
+    }
+  }
+  catch * {
+    fn:error("fots:set-context-item")
+  }
+};
+
+declare %private function fots:check-should-run-test(
+  $deps as element(fots:dependency)*
+) as xs:boolean {
+  let $values := for $dep in $deps return fn:exists($dep[@satisfied="false"])
+  return
+    switch(fn:count(fn:distinct-values($values)))
+    case xs:integer(2) return fn:false()
+    case xs:integer(1) return fn:boolean(fn:not(fn:distinct-values($values)))
+    default return fn:true()
+};
+
+declare %private function fots:add-xquery-30(
+  $deps as element(fots:dependency)*
+) as xs:string? {
+  let $val := for $dep in $deps
+              where $dep[@type="spec"] and fn:contains(fn:data($dep/@value), "30")
+              return fn:true()
+  return
+    if($val[1])
+    then "xquery version '3.0';"
+    else ()
+};
+
+declare %private function fots:enable-HOF-feature(
+  $deps as element(fots:dependency)*
+) as xs:string? {
+  let $val := for $dep in $deps
+              where $dep[@type="spec"] and fn:contains(fn:data($dep/@value), "30")
+              return fn:true()
+  return
+    if($val[1]) 
+    then concat("declare namespace o = 'http://www.zorba-xquery.com/options/features';",
+                "declare option o:enable 'hof';")
+    else ()
+};
+
+(: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 %private %ann:nondeterministic function fots: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))
+};

=== 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-08-01 08:12:20 +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

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to