|
| 1 | +(: |
| 2 | + : eXist-db Open Source Native XML Database |
| 3 | + : Copyright (C) 2001 The eXist-db Authors |
| 4 | + : |
| 5 | + : info@exist-db.org |
| 6 | + : http://www.exist-db.org |
| 7 | + : |
| 8 | + : This library is free software; you can redistribute it and/or |
| 9 | + : modify it under the terms of the GNU Lesser General Public |
| 10 | + : License as published by the Free Software Foundation; either |
| 11 | + : version 2.1 of the License, or (at your option) any later version. |
| 12 | + : |
| 13 | + : This library is distributed in the hope that it will be useful, |
| 14 | + : but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | + : Lesser General Public License for more details. |
| 17 | + : |
| 18 | + : You should have received a copy of the GNU Lesser General Public |
| 19 | + : License along with this library; if not, write to the Free Software |
| 20 | + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | + :) |
| 22 | +xquery version "3.1"; |
| 23 | + |
| 24 | +module namespace helper="http://exist-db.org/xquery/test/util/helper"; |
| 25 | +import module namespace fixtures="http://exist-db.org/xquery/test/util/fixtures" at "fixtures.xqm"; |
| 26 | +import module namespace file="http://expath.org/ns/file"; |
| 27 | +import module namespace xmldb="http://exist-db.org/xquery/xmldb"; |
| 28 | +import module namespace util="http://exist-db.org/xquery/util"; |
| 29 | + |
| 30 | +declare namespace utilns="http://exist-db.org/xquery/util"; |
| 31 | + |
| 32 | +declare variable $helper:error := xs:QName("helper:assert-sync-error"); |
| 33 | + |
| 34 | +declare variable $helper:path-separator := util:system-property("file.separator"); |
| 35 | + |
| 36 | +(: |
| 37 | +/db |
| 38 | + /file-module-test |
| 39 | + /data |
| 40 | + test-data.xml |
| 41 | + test-text.txt |
| 42 | + test-query.xq |
| 43 | + bin |
| 44 | +:) |
| 45 | +declare function helper:setup-db() as empty-sequence() { |
| 46 | + let $_ := ( |
| 47 | + xmldb:create-collection("/db", $fixtures:collection-name), |
| 48 | + helper:create-db-resource($fixtures:collection, "test-text.txt", $fixtures:TXT), |
| 49 | + helper:create-db-resource($fixtures:collection, "test-query.xq", $fixtures:XQY), |
| 50 | + helper:create-db-resource($fixtures:collection, "bin", $fixtures:BIN), |
| 51 | + |
| 52 | + xmldb:create-collection($fixtures:collection, $fixtures:child-collection-name), |
| 53 | + helper:create-db-resource($fixtures:child-collection, "test-data.xml", $fixtures:XML) |
| 54 | + ) |
| 55 | + return () |
| 56 | +}; |
| 57 | + |
| 58 | +declare function helper:clear-db() { |
| 59 | + xmldb:remove($fixtures:collection) |
| 60 | +}; |
| 61 | + |
| 62 | +declare function helper:create-db-resource($collection as xs:string, $resource as xs:string, $content as item()) as empty-sequence() { |
| 63 | + let $_ := xmldb:store($collection, $resource, $content) |
| 64 | + return () |
| 65 | +}; |
| 66 | + |
| 67 | +declare function helper:modify-db-resource($collection as xs:string, $resource as xs:string) as empty-sequence() { |
| 68 | + let $_ := xmldb:touch($collection, $resource, $fixtures:mod-date-2) |
| 69 | + return () |
| 70 | +}; |
| 71 | + |
| 72 | +declare function helper:clear-suite-fs ($suite as xs:string) as empty-sequence() { |
| 73 | + let $dir := |
| 74 | + helper:glue-path(( |
| 75 | + util:system-property("java.io.tmpdir"), |
| 76 | + $suite |
| 77 | + )) |
| 78 | + return |
| 79 | + if (file:exists($dir)) then |
| 80 | + let $_ := file:delete($dir, true()) |
| 81 | + return () |
| 82 | + else () |
| 83 | +}; |
| 84 | + |
| 85 | +declare function helper:clear-fs ($directory as xs:string) as empty-sequence() { |
| 86 | + if (file:exists($directory)) then |
| 87 | + let $_ := file:delete($directory, true()) |
| 88 | + return () |
| 89 | + else () |
| 90 | +}; |
| 91 | + |
| 92 | +declare function helper:get-test-directory ($suite as xs:string) as xs:string { |
| 93 | + helper:glue-path(( |
| 94 | + util:system-property("java.io.tmpdir"), |
| 95 | + $suite, |
| 96 | + util:uuid() |
| 97 | + )) |
| 98 | +}; |
| 99 | + |
| 100 | +declare function helper:glue-path ($parts as xs:string+) as xs:string { |
| 101 | + string-join($parts, $helper:path-separator) |
| 102 | +}; |
| 103 | + |
| 104 | +(: |
| 105 | + : clear FS state and simulate additional data on the file system in a specific directory |
| 106 | + : @returns given directory to allow use in pipeline (chain of arrow operators) |
| 107 | + :) |
| 108 | +declare function helper:setup-fs-extra ($directory as xs:string) as xs:string { |
| 109 | + let $_ := file:create-dir($directory) |
| 110 | + let $_ := file:create-dir(helper:glue-path(($directory, "test"))) |
| 111 | + let $_ := ( |
| 112 | + file:write-binary( |
| 113 | + helper:glue-path(($directory, ".env")), |
| 114 | + util:string-to-binary("SERVER_SECRET=123!")), |
| 115 | + file:write-binary( |
| 116 | + helper:glue-path(($directory, "test", "three.s")), |
| 117 | + util:string-to-binary("...")) |
| 118 | + ) |
| 119 | + return $directory |
| 120 | +}; |
| 121 | + |
| 122 | +declare function helper:get-deleted-from-sync-result ($result as element(utilns:sync)) as xs:string* { |
| 123 | + $result//utilns:delete/@name/string() |
| 124 | +}; |
| 125 | + |
| 126 | +declare function helper:get-dir-from-sync-result ($result as element(utilns:sync)) as xs:string* { |
| 127 | + $result/@utilns:dir/string() |
| 128 | +}; |
| 129 | + |
| 130 | +declare function helper:get-updated-from-sync-result ($result as element(utilns:sync)) as xs:string* { |
| 131 | + $result//utilns:update/@name/string() |
| 132 | +}; |
| 133 | + |
| 134 | +declare function helper:list-files-and-directories ($directory as xs:string) as xs:string* { |
| 135 | + (: EXPath file:list returns relative path strings, directories end with separator :) |
| 136 | + for $entry in file:list($directory) |
| 137 | + return |
| 138 | + (: strip trailing separator from directory names :) |
| 139 | + if (ends-with($entry, file:dir-separator())) |
| 140 | + then substring($entry, 1, string-length($entry) - string-length(file:dir-separator())) |
| 141 | + else $entry |
| 142 | +}; |
| 143 | + |
| 144 | +declare function helper:sync-with-options ($directory as xs:string, $options as item()?) as element(utilns:sync) { |
| 145 | + util:file-sync($fixtures:collection, $directory, $options)/* |
| 146 | +}; |
| 147 | + |
| 148 | +declare function helper:assert-sync-result ( |
| 149 | + $result as document-node(element(utilns:sync)), |
| 150 | + $expected as map(xs:string, xs:string*) |
| 151 | +) as xs:boolean { |
| 152 | + helper:assert-permutation-of( |
| 153 | + $expected?updated, |
| 154 | + helper:get-updated-from-sync-result($result/*), |
| 155 | + "updated" |
| 156 | + ) |
| 157 | + and |
| 158 | + helper:assert-permutation-of( |
| 159 | + $expected?deleted, |
| 160 | + helper:get-deleted-from-sync-result($result/*), |
| 161 | + "deleted" |
| 162 | + ) |
| 163 | + and |
| 164 | + helper:assert-permutation-of( |
| 165 | + $expected?fs, |
| 166 | + helper:get-dir-from-sync-result($result/*) |
| 167 | + => helper:list-files-and-directories(), |
| 168 | + "filesystem" |
| 169 | + ) |
| 170 | +}; |
| 171 | + |
| 172 | +declare function helper:assert-permutation-of( |
| 173 | + $expected as xs:anyAtomicType*, |
| 174 | + $actual as xs:anyAtomicType*, |
| 175 | + $label as xs:string |
| 176 | +) as xs:boolean { |
| 177 | + let $test := fold-left( |
| 178 | + $expected, |
| 179 | + [true(), $actual], |
| 180 | + helper:permutation-reducer#2 |
| 181 | + ) |
| 182 | + |
| 183 | + return |
| 184 | + if (empty($expected) and not(empty($actual))) |
| 185 | + then error($helper:error, |
| 186 | + "Assertion failed (" || $label || "): expected empty sequence" || |
| 187 | + " but got (" || string-join($actual, ", ") || ")") |
| 188 | + else if (not($test?1 or exists($test?2))) |
| 189 | + then error($helper:error, |
| 190 | + "Assertion failed (" || $label || "): expected permutation of " || |
| 191 | + "(" || string-join($expected, ", ") || ")" || |
| 192 | + " but got (" || string-join($actual, ", ") || ")") |
| 193 | + else true() |
| 194 | +}; |
| 195 | + |
| 196 | +declare function helper:permutation-reducer ($result, $next) as array(*) { |
| 197 | + let $first-index := index-of($result?2, $next)[1] |
| 198 | + return [ |
| 199 | + $result?1 and $first-index > 0, |
| 200 | + helper:maybe-remove-item-at-index($result?2, $first-index) |
| 201 | + ] |
| 202 | +}; |
| 203 | + |
| 204 | +declare function helper:maybe-remove-item-at-index($sequence as xs:anyAtomicType*, $index as xs:integer?) as xs:anyAtomicType* { |
| 205 | + if ($index = 1) |
| 206 | + then subsequence($sequence, 2) |
| 207 | + else if ($index > 1) |
| 208 | + then ( |
| 209 | + subsequence($sequence, 1, $index - 1), |
| 210 | + subsequence($sequence, $index + 1) |
| 211 | + ) |
| 212 | + else $sequence (: do nothing - will be handled later :) |
| 213 | +}; |
| 214 | + |
| 215 | +declare function helper:assert-file-contents($expected as xs:string, $path-parts as xs:string+) as xs:boolean { |
| 216 | + let $path := helper:glue-path($path-parts) |
| 217 | + let $actual := file:read-text($path) |
| 218 | + |
| 219 | + return |
| 220 | + if ( |
| 221 | + exists($actual) and |
| 222 | + count($actual) = 1 and |
| 223 | + $actual eq $expected) |
| 224 | + then true() |
| 225 | + else error( |
| 226 | + $helper:error, |
| 227 | + "File Content Assertion failed: expected file " || $path || " " || |
| 228 | + "to contain string " || "<[" || $expected || "]>" || |
| 229 | + " but was <[" || $actual || "]>" |
| 230 | + ) |
| 231 | +}; |
0 commit comments