001: package gnu.xquery.testsuite;
002:
003: import gnu.expr.*;
004: import gnu.mapping.*;
005: import gnu.xquery.lang.*;
006: import gnu.text.*;
007:
008: public class TestMisc {
009: static {
010: XQuery.registerEnvironment();
011: }
012: static XQuery interp = XQuery.getInstance();
013: static Environment env = Environment.getCurrent();
014:
015: static int expectedPasses = 0;
016: static int unexpectedPasses = 0;
017: static int expectedFailures = 0;
018: static int unexpectedFailures = 0;
019: static boolean verbose = false;
020: static String failureExpectedNext = null;
021:
022: public static void main(String[] args) {
023: // gnu.expr.ModuleExp.dumpZipPrefix = "kawa-zip-dump-";
024: // Compilation.debugPrintExpr = true;
025: // Compilation.debugPrintFinalExpr = true;
026:
027: evalTest("3.5+1", "4.5");
028: evalTest("3.5+1 ,4*2.5", "4.5 10");
029: evalTest("3<5", "true");
030: evalTest("let $x:=3+4 return $x", "7");
031: evalTest("let $x:=3+4 return <a>{$x}</a>", "<a>7</a>");
032: // We resolve $request and $response to servlet request/response,
033: // but only when they're not lexially bound.
034: evalTest(
035: "let $request:=2, $response:=3 return ($request+$response)",
036: "5");
037:
038: evalTest("some $x in (1, 2, 3), $y in (2, 3, 4)"
039: + " satisfies $x + $y = 4", "true");
040: evalTest("every $x in (1, 2, 3), $y in (2, 3, 4)"
041: + " satisfies $x + $y = 4", "false");
042: evalTest("every $x in (11, 12, 13), $y in (2, 3, 4)"
043: + " satisfies $x > $y", "true");
044:
045: evalTest("for $y in (4,5,2+4) return <b>{10+$y}</b>",
046: "<b>14</b><b>15</b><b>16</b>");
047: evalTest("for $i in (1 to 10) where ($i mod 2)=1 return 20+$i",
048: "21 23 25 27 29");
049: evalTest("for $car at $i in ('Ford', 'Chevy'),"
050: + "$pet at $j in ('Cat', 'Dog') "
051: + "return ($i, '/', $car, '/', $j, '/', $pet, ';')",
052: "1/Ford/1/Cat;1/Ford/2/Dog;2/Chevy/1/Cat;2/Chevy/2/Dog;");
053:
054: evalTest("(3,4,5)[3]", "5");
055: evalTest("1,((2,3)[false()]),5", "1 5");
056: evalTest("1,((2 to 4)[true()]),5", "1 2 3 4 5");
057: evalTest("(for $y in (5,4) return <b>{10+$y}</b>)[2]",
058: "<b>14</b>");
059: evalTest(
060: "for $a in (<a><b c='1' d='3'/><b c='2' d='6'/></a>)/b/@c"
061: + " return concat('c: ', $a, ' d: ', $a/../@d, ';')",
062: "c: 1 d: 3;c: 2 d: 6;");
063:
064: String tabNsNodes = " xmlns:h=\"H\" xmlns:j=\"J\" xmlns:k=\"J\"";
065: evalTest(
066: "doc('tab.xml')/result",
067: "<result"
068: + tabNsNodes
069: + ">\n"
070: + "<row>\n"
071: + "<fld1>a1</fld1>\n"
072: + "<fld2 align=\"right\"><!--ignore-this-comment-->12</fld2>\n"
073: + "</row>\n"
074: + "<row>\n"
075: + "<fld1 align=\"left\">b1</fld1>\n"
076: + "<fld2 align=\"right\">22</fld2>\n"
077: + "</row>\n"
078: + "<h:row>\n"
079: + "<j:fld1><![CDATA[c]]><![CDATA[1]]></j:fld1>\n"
080: + "<h:fld2><![CDATA[33]]></h:fld2>\n"
081: + "<j:fld3>44</j:fld3>\n"
082: + "<k:fld1>c2</k:fld1>\n" + "</h:row>\n"
083: + "</result>");
084: evalTest(
085: "doc('tab.xml')/result/row/fld2",
086: "<fld2"
087: + tabNsNodes
088: + " align=\"right\"><!--ignore-this-comment-->12</fld2>"
089: + "<fld2" + tabNsNodes
090: + " align=\"right\">22</fld2>");
091: evalTest(
092: "doc('tab.xml')/result/row[fld2]",
093: "<row"
094: + tabNsNodes
095: + ">\n"
096: + "<fld1>a1</fld1>\n"
097: + "<fld2 align=\"right\"><!--ignore-this-comment-->12</fld2>\n</row>"
098: + "<row" + tabNsNodes + ">\n"
099: + "<fld1 align=\"left\">b1</fld1>\n"
100: + "<fld2 align=\"right\">22</fld2>\n"
101: + "</row>");
102: evalTest(
103: "doc('tab.xml')/result/row/*",
104: "<fld1"
105: + tabNsNodes
106: + ">a1</fld1><fld2"
107: + tabNsNodes
108: + " align=\"right\"><!--ignore-this-comment-->12</fld2><fld1"
109: + tabNsNodes + " align=\"left\">b1</fld1><fld2"
110: + tabNsNodes + " align=\"right\">22</fld2>");
111:
112: evalTest("doc('tab.xml')/result/row[2]", "<row" + tabNsNodes
113: + ">\n" + "<fld1 align=\"left\">b1</fld1>\n"
114: + "<fld2 align=\"right\">22</fld2>\n" + "</row>");
115: evalTest("for $x in doc('tab.xml')/result/row[2]/node()"
116: + " return ('[',$x,']')", "[\n][<fld1" + tabNsNodes
117: + " align=\"left\">b1</fld1>][\n" + "][<fld2"
118: + tabNsNodes + " align=\"right\">22</fld2>][\n]");
119: evalTest("for $x in doc('tab.xml')/result/row[2]/text()"
120: + " return ('[',$x,']')", "[\n][\n][\n]");
121: evalTest("for $x in doc('tab.xml')/result/row[2]//text()"
122: + " return ('[',$x,']')", "[\n][b1][\n][22][\n]");
123: evalTest(
124: "doc('tab.xml')/result/row/*[2]",
125: "<fld2"
126: + tabNsNodes
127: + " align=\"right\"><!--ignore-this-comment-->12</fld2>"
128: + "<fld2" + tabNsNodes
129: + " align=\"right\">22</fld2>");
130:
131: evalTest(
132: "for $x in <T>r1<fld1>a1</fld1><fld3/>r2<fld2>12</fld2></T>"
133: + " /node()" + " return ('[',$x,']')",
134: "[r1][<fld1>a1</fld1>][<fld3 />][r2][<fld2>12</fld2>]");
135:
136: evalTest(
137: "(doc('tab.xml')/result/row/*)[2]",
138: "<fld2"
139: + tabNsNodes
140: + " align=\"right\"><!--ignore-this-comment-->12</fld2>");
141: evalTest(
142: "(doc('tab.xml')/result/row/*)[position()>1]",
143: "<fld2"
144: + tabNsNodes
145: + " align=\"right\"><!--ignore-this-comment-->12</fld2>"
146: + "<fld1" + tabNsNodes
147: + " align=\"left\">b1</fld1>" + "<fld2"
148: + tabNsNodes + " align=\"right\">22</fld2>");
149: evalTest("(doc('tab.xml')/result/row/*)[position()>1][2]",
150: "<fld1" + tabNsNodes + " align=\"left\">b1</fld1>");
151:
152: evalTest(
153: "doc('tab.xml')/result/row/(fld2,fld1)",
154: "<fld1"
155: + tabNsNodes
156: + ">a1</fld1>"
157: + "<fld2"
158: + tabNsNodes
159: + " align=\"right\"><!--ignore-this-comment-->12</fld2>"
160: + "<fld1" + tabNsNodes
161: + " align=\"left\">b1</fld1>" + "<fld2"
162: + tabNsNodes + " align=\"right\">22</fld2>");
163:
164: evalTest("string(doc('tab.xml'))",
165: "\n\na1\n12\n\n\nb1\n22\n\n\nc1\n33\n44\nc2\n\n\n");
166: evalTest("string(doc('tab.xml'))",
167: "\n\na1\n12\n\n\nb1\n22\n\n\nc1\n33\n44\nc2\n\n\n");
168: evalTest("string(doc('tab.xml')/result/row/fld1/@align)",
169: "left");
170: evalTest("doc('tab.xml')/result/row/fld2/@align/string()",
171: "rightright");
172:
173: evalTest(
174: "for $x in children(<a>xy{3+4}kl<c>def</c>{9}{11}</a>)"
175: + " return ('[',$x,']')",
176: "[xy 7 kl][<c>def</c>][9 11]");
177: evalTest("children(<a>xy{3+4}kl<c>def</c>{9}{11}</a>)",
178: "xy 7 kl<c>def</c>9 11");
179:
180: evalTest("<a>aab</a> ='aab'", "true");
181: evalTest("<a>abc</a>='abb'", "false");
182:
183: evalTest("string(<a>{'aa''bbXccZdd'}</a>)",
184: "aa'bbXccZdd");
185:
186: evalTest(
187: "doc('tab.xml')/result/row[fld1]",
188: "<row"
189: + tabNsNodes
190: + ">\n"
191: + "<fld1>a1</fld1>\n"
192: + "<fld2 align=\"right\"><!--ignore-this-comment-->12</fld2>\n</row>"
193: + "<row" + tabNsNodes + ">\n"
194: + "<fld1 align=\"left\">b1</fld1>\n"
195: + "<fld2 align=\"right\">22</fld2>\n"
196: + "</row>");
197: evalTest("doc('tab.xml')/result/row[fld3]", "");
198: evalTest("doc('tab.xml')/result/row/fld1[@align]", "<fld1"
199: + tabNsNodes + " align=\"left\">b1</fld1>");
200: evalTest(
201: "doc('tab.xml')/result/row/fld2[@align]",
202: "<fld2"
203: + tabNsNodes
204: + " align=\"right\"><!--ignore-this-comment-->12</fld2>"
205: + "<fld2" + tabNsNodes
206: + " align=\"right\">22</fld2>");
207: evalTest("'a',doc('tab.xml')/result/row/fld1[@align='left']",
208: "a<fld1" + tabNsNodes + " align=\"left\">b1</fld1>");
209: evalTest("'a',doc('tab.xml')/result/row/fld1[@align='right']",
210: "a");
211:
212: evalTest(
213: "let $x:=12,\n"
214: + " $y:=<a>{$x+$x}</a>\n"
215: + " return <b atr1='11' atr2=\"{$x}\">{($y,99,$y)}</b>",
216: "<b atr1=\"11\" atr2=\"12\"><a>24</a>99<a>24</a></b>");
217:
218: evalTest(
219: "let $el := 'elm' return "
220: + "document{element {$el} {attribute at{\"abc\"}, \"data\"}}/elm",
221: "<elm at=\"abc\">data</elm>");
222:
223: evalTest("let $a := <a at1='val1'><b/><c/></a>,"
224: + " $b0 := <b/>," + " $b := $a/b return"
225: + " ($a is $a, $a << $b, $b >> $b,"
226: + " $a isnot $b, $b, $b0, $b is $b0)",
227: "true true false true <b /> <b /> false");
228: evalTest(
229: "let $a := <a at1='val1'><b/><c/></a>,"
230: + " $b := $a/b, $c := $a/c return"
231: + " for $n in distinct-nodes(($c, $a/@at1, $a, $c, $b, $b, $c))"
232: + " return ('[', $n, ']')",
233: "[<a at1=\"val1\"><b /><c /></a>][ at1=\"val1\"][<b />][<c />]");
234:
235: // Boundary whitsapce (boundary-space) tests:
236: evalTest(
237: "declare boundary-space preserve;\n"
238: + "for $n in (<a> <b/> {' x '} </a>)/node() return ($n,';')",
239: " ;<b/>; x ;");
240: evalTest(
241: "declare boundary-space strip;\n"
242: + "for $n in (<a> <b/> {' x '} </a>)/node() return ($n,';')",
243: "<b/>; x ;");
244: evalTest(
245: "declare boundary-space strip;\n"
246: + "for $n in (<a> x <b/> y<c/> </a>)/node() return ($n,';')",
247: " x ;<b/>; y;<c/>; ;");
248: evalTest("for $n in (<a> <b/> </a>)/node() return ($n,';')",
249: "<b/>;");
250: evalTest("<a> {3} {4} </a>", "<a>34</a>");
251: // This actually succeeds because evalTest ignores spaces.
252: // failureExpectedNext = "fix space handling in constructors";
253: evalTest("<a>{3,4}{5,6}</a>", "<a>3 45 6</a>");
254: failureExpectedNext = "fix space handling in constructors";
255: evalTest("let $x := <a>{3,4}{5,6}</a> return <b>{$x, $x}</b>",
256: "<ba><a>3 45 6</a><a>3 45 6</a></b>");
257: evalTest(
258: "for $n in <a><?xq doit?>abc<![CDATA[<X>]]>d<!--a comment--></a>/node()"
259: + " return ($n,';')",
260: "<?xq doit?>;abc<![CDATA[<X>]]>d;<!--a comment-->;");
261: evalTest(
262: "for $n in <a><?xq doit?>abc<![CDATA[<X>]]>d<!--a comment--></a>/node()"
263: + " return (string($n),';')",
264: "doit;abc<X>d;a comment;");
265: evalTest(
266: "string(<a><?xq doit?>abc<![CDATA[<X>]]>d<!--a comment--></a>)",
267: "abc<X>d");
268:
269: // Simple namespace tests.
270: evalTest("declare namespace xx='XXX';\n <xx:a>XX</xx:a>",
271: "<xx:a xmlns:xx=\"XXX\">XX</xx:a>");
272: evalTest(
273: "declare namespace x1='XXX';\n declare namespace x2='XXX';\n"
274: + "(<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/x2:ab/string()",
275: "X1X2");
276: evalTest(
277: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
278: + "string((<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/x2:ab)",
279: "X2");
280: evalTest(
281: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
282: + "(<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/*/string()",
283: "X1X2");
284: evalTest(
285: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
286: + "(<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/*:*/string()",
287: "X1X2");
288: evalTest(
289: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
290: + "string((<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/x1:*)",
291: "X1");
292: evalTest(
293: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
294: + "(<top><x1:ab>X1</x1:ab><x2:ab>X2</x2:ab></top>)/*:ab/string()",
295: "X1X2");
296: evalTest(
297: "declare namespace x1='XXX';\n declare namespace x2='YYY';\n"
298: + "string((<top><x1:ab>X1</x1:ab><x2:cd>X2</x2:cd></top>)/*:cd)",
299: "X2");
300: evalTest("declare namespace h='H';\n"
301: + "string(doc('tab.xml')/result/h:row)",
302: "\nc1\n33\n44\nc2\n");
303: evalTest("declare namespace xx='H';\n"
304: + "doc('tab.xml')/result/xx:row/string()",
305: "\nc1\n33\n44\nc2\n");
306: evalTest("doc('tab.xml')/result/*:row/string()",
307: "\na1\n12\n\nb1\n22\n\nc1\n33\n44\nc2\n");
308: evalTest("doc('tab.xml')/result/*:row/*:fld1/string()",
309: "a1b1c1c2");
310: evalTest("declare namespace k='J';\n"
311: + "doc('tab.xml')/result/*:row/k:fld1/string()", "c1c2");
312: evalTest("declare namespace k='J';\n"
313: + "string(doc('tab.xml')/result/*:row[k:fld1])",
314: "\nc1\n33\n44\nc2\n");
315: evalTest(
316: "declare namespace m1 = 'bb'; declare namespace m2 = 'cc';"
317: + "let $m1:x := 3 return let $m2:x := 4 return"
318: + " <m2:a a:c='{$a:x}' xmlns:a='bb'>{ count($a:x) }</m2:a>",
319: "<m2:a xmlns:a=\"bb\" xmlns:m2=\"cc\" a:c=\"3\">1</m2:a>");
320:
321: evalTest(
322: "doc('tab.xml')/result/row[1]/descendant::*",
323: "<fld1"
324: + tabNsNodes
325: + ">a1</fld1>"
326: + "<fld2"
327: + tabNsNodes
328: + " align=\"right\"><!--ignore-this-comment-->12</fld2>");
329: evalTest(
330: "for $x in doc('tab.xml')/result/row[1]/descendant::node() return ($x,';')",
331: "\n;<fld1"
332: + tabNsNodes
333: + ">a1</fld1>;a1;\n;"
334: + "<fld2"
335: + tabNsNodes
336: + " align=\"right\"><!--ignore-this-comment-->12</fld2>;<!--ignore-this-comment-->;12;\n;");
337: evalTest("doc('tab.xml')/result/row[1]/descendant::text()",
338: "a112");
339: evalTest(
340: "doc('tab.xml')/result/row[1]/descendant-or-self::*",
341: "<row"
342: + tabNsNodes
343: + "><fld1>a1</fld1>"
344: + "<fld2 align=\"right\"><!--ignore-this-comment-->12</fld2></row>"
345: + "<fld1"
346: + tabNsNodes
347: + ">a1</fld1>"
348: + "<fld2"
349: + tabNsNodes
350: + " align=\"right\"><!--ignore-this-comment-->12</fld2>");
351:
352: evalTest(
353: "for $n in doc('tab.xml')/result/* return node-name($n)",
354: "row row h:row");
355:
356: evalTest("for $n in doc('tab.xml')/result/row/* "
357: + "return local-name-from-QName(node-name($n))",
358: "fld1 fld2 fld1 fld2");
359: evalTest("declare namespace h='H';\n"
360: + " for $n in doc('tab.xml')/result/*:row/* "
361: + "return (prefix-from-QName(node-name($n)),';')",
362: " ; ; ; ; j ; h ; j ; k ;");
363: evalTest(
364: "for $n in doc('tab.xml')/result/*:row/*:fld1 "
365: + "return <n>{namespace-uri-from-QName(node-name($n))}</n>",
366: "<n /><n /><n>J</n><n>J</n>");
367: evalTest("for $n in doc('tab.xml')/result/*:row/*:fld1 return "
368: + "('[', for $p in ('', 'k', 'h') return"
369: + " (namespace-uri-for-prefix($p,$n),';'), ']')",
370: "[;J;H;][;J;H;][;J;H;][;J;H;]");
371:
372: // Based on bugs reported by Francois Leygues <vizawalou@wanadoo.fr>:
373: evalTest("let $bx := <b x='xx'></b> return"
374: + " let $x := <a>{for $y in $bx return $y}</a>"
375: + " return $x/b", "<b x=\"xx\" />");
376: evalTest("element r {let $y := <b x='1'/>"
377: + " let $x:=<a>{$y}</a> return $x/b/@x}",
378: "<r x=\"1\" />");
379: evalTest(
380: "declare function local:x(){<a><b x='1'/><b x='2'/></a>};"
381: + " let $i := <a>{for $a in local:x()/b return $a}</a> return $i/b/@x",
382: " x=\"1\" x=\"2\"");
383:
384: evalTest(
385: "declare function local:s(){ <a x='10'>{for $n in (<b x='2'/>) return ($n) }</a>};"
386: + " let $st := local:s()/b return ("
387: + " '[',$st/@x ,'] [',$st ,']')",
388: "[ x=\"2\"] [<b x=\"2\" />]");
389:
390: // Testcase from <Seshukumar_Adiraju@infosys.com>:
391: evalTest(
392: "let $books := "
393: + "<books><book id='book1'/><book id='book2'/></books> "
394: + "for $book in $books/book return <p>{string($book/@id)}</p>",
395: "<p>book1</p><p>book2</p>");
396:
397: evalTest(
398: "for $n in children(<a>xx<b/>yy</a>) return $n instance of node()",
399: "true true true");
400: evalTest(
401: "for $n in children(<a>xx<b/>yy</a>) return $n instance of text ( )",
402: "true false true");
403: evalTest(
404: "for $n in children(<a>xx<b/>yy</a>) return $n instance of element(a)",
405: "false false false");
406: evalTest(
407: "for $n in <a>xx<b/>yy</a>/node() return $n instance of element(b)",
408: "false true false");
409: // FIXME: evalTest("<a>xx<b/>yy</a>/node() instance of node()", "false");
410: evalTest("<a>xx<b/>yy</a>/node() instance of node()?", "false");
411: evalTest("<a>xx<b/>yy</a>/node() instance of node()+", "true");
412: evalTest("<a>xx<b/>yy</a>/node() instance of node()*", "true");
413: evalTest("<a>xx<b/>yy</a>/node() instance of item()+", "true");
414: evalTest("(3,4,5) instance of item()+", "true");
415: evalTest("('a','b') instance of string+", "true");
416: evalTest("(2,3) instance of string?", "false");
417: evalTest("(2,3) instance of string+", "false");
418: evalTest("() instance of string?", "true");
419: evalTest("() instance of string+", "false");
420: evalTest("() instance of string*", "true");
421: evalTest("('2') instance of string?", "true");
422: evalTest("('2') instance of string+", "true");
423: evalTest("('2') instance of string*", "true");
424: evalTest("('2','3') instance of string?", "false");
425: evalTest("('2','3') instance of string+", "true");
426: evalTest("('2','3') instance of string*", "true");
427:
428: evalTest("declare namespace Int='class:java.lang.Integer';\n"
429: + "Int:toHexString(266)", "10a");
430: evalTest(
431: "declare namespace File='class:java.io.File';\n"
432: + "declare function local:make-file ($x as string) {File:new($x)};\n"
433: + "declare function local:parent ($x) {java.io.File:getParent($x)};\n"
434: + "local:parent(local:make-file('dir/mine.txt'))",
435: "dir");
436: evalTest("java.lang.Integer:toHexString(255)", "ff");
437:
438: // String functions
439: evalTest("substring('motor car', 6)", "car");
440: evalTest("substring('metadata', 4, 3)", "ada");
441: // evalTest("substring('metadata', -INF, 3)", "met");
442:
443: evalTest("(1 to 20)[. mod 5 = 0]", "5 10 15 20");
444: evalTest("(1 to 20)[. mod 5 ge 3]", "3 4 8 9 13 14 18 19");
445: evalTest("1,(99 to 0),3", "1 3");
446: evalTest("-10 to -2", "-10 -9 -8 -7 -6 -5 -4 -3 -2");
447:
448: String some_elements = "let $top := <top><a/><b/><c/><d/></top>,"
449: + " $a:=$top/a, $b:=$top/b, $c:=$top/c, $d:=$top/d return ";
450: evalNodeNames(some_elements + "($b, $a) union ($a, $b)", "a;b;");
451: evalNodeNames(some_elements + "($b, $a) union ($b, $c)",
452: "a;b;c;");
453: evalNodeNames(some_elements + "($b, $a) intersect ($a, $b)",
454: "a;b;");
455: evalNodeNames(some_elements + "($b, $a) intersect ($b, $c)",
456: "b;");
457: evalNodeNames(some_elements + "($b, $a) except ($a, $b)", "");
458: evalNodeNames(some_elements + "($b, $a) except ($b, $c)", "a;");
459: evalNodeNames(some_elements
460: + "($b, $a, $b, $d) intersect ($b, $d)", "b;d;");
461: evalNodeNames(some_elements
462: + "($b, $a, $b, $d) except ($b, $d)", "a;");
463: evalNodeNames(some_elements + "($b, $a, $b, $d) except ()",
464: "a;b;d;");
465:
466: // Check for catching errors:
467: evalTest("+ +",
468: "*** syntax error - <string>:1:4: missing expression [XPST0003]");
469:
470: evalTest(
471: "declare namespace x1='XXX",
472: "*** caught SyntaxException - <string>:1:22: "
473: + "unexpected end-of-file in string starting here [XPST0003]");
474:
475: evalTest(
476: "unescaped-data('<?--->'),let $x:=unescaped-data('an &oslash;') return <b>{unescaped-data('<![CDATA[saw]]>')} {$x}</b>",
477: "<?---><b><![CDATA[saw]]> an ø</b>");
478:
479: evalTestIdAttrs(
480: "doc('outline.xml')/book/part/chapter/ancestor::*",
481: "b1;P1;");
482: evalTestIdAttrs("doc('outline.xml')/book/part/"
483: + "chapter/ancestor-or-self::node()", ";b1;P1;c1;c2;");
484: evalTestIdAttrs("doc('outline.xml')//"
485: + "section[@id='s1']/following-sibling::*", "s2;s3;");
486: evalTestIdAttrs("doc('outline.xml')//chapter/self::*", "c1;c2;");
487: evalTestIdAttrs("doc('outline.xml')//"
488: + "para[@id='p31']/preceding::*", "s1;s11;s2;");
489: evalTestIdAttrs("doc('outline.xml')//"
490: + "section[@id='s5']/preceding-sibling::*", "s4;");
491: evalTestIdAttrs("doc('outline.xml')//"
492: + "chapter[@id='c1']/following::*", "c2;s4;s5;");
493: evalTestIdAttrs("doc('outline.xml')//"
494: + "section[@id='s1']/(/book)", "b1;");
495: evalTestIdAttrs("doc('outline.xml')//"
496: + "section[@id='s1']/(//chapter)", "c1;c2;");
497:
498: evalTest(
499: "declare namespace XQuery = 'class:gnu.xquery.lang.XQuery';"
500: + "XQuery:eval-with-focus(XQuery:getInstance(),"
501: + " '<r pos=\"{position()}\">{.}</r>', (<b/>, 3))",
502: "<r pos=\"1\"><b /></r><r pos=\"2\">3</r>");
503: evalTest(
504: "declare namespace XQuery = 'class:gnu.xquery.lang.XQuery';"
505: + "XQuery:eval-with-focus(XQuery:getInstance(),"
506: + " '<r pos=\"{position()}\">{.}</r>', <b/>, 3, 4)",
507: "<r pos=\"3\"><b /></r>");
508:
509: Object r;
510: String e = "<r pos='{position()}' size='{last()}'>{.}</r>";
511: try {
512: r = toString(interp.evalWithFocus(e, interp.eval("2,3,4")));
513: } catch (Throwable ex) {
514: r = ex;
515: }
516: matchTest(e, r, "<r pos=\"1\" size=\"3\">2</r>"
517: + "<r pos=\"2\" size=\"3\">3</r>"
518: + "<r pos=\"3\" size=\"3\">4</r>");
519: try {
520: r = toString(interp.evalWithFocus(e, interp.eval("<b/>"),
521: 4, 10));
522: } catch (Throwable ex) {
523: r = ex;
524: }
525: matchTest(e, r, "<r pos=\"4\" size=\"10\"><b/></r>");
526:
527: printSummary();
528: }
529:
530: public static boolean printSummary() {
531: System.out.println("# of expected passes "
532: + expectedPasses);
533: if (expectedFailures > 0)
534: System.out.println("# of expected failures "
535: + expectedFailures);
536: if (unexpectedPasses > 0)
537: System.out.println("# of unexpected passes "
538: + unexpectedPasses);
539: if (unexpectedFailures > 0)
540: System.out.println("# of unexpected failures "
541: + unexpectedFailures);
542: return unexpectedFailures != 0;
543: }
544:
545: /** True if the two string match, ignoring unquoted white-space. */
546: public static boolean matches(String str1, String str2) {
547: int i = 0;
548: int j = 0;
549: char quote = 0;
550: for (;;) {
551: char x, y;
552: for (;;) {
553: if (i >= str1.length()) {
554: x = 0;
555: break;
556: }
557: x = str1.charAt(i++);
558: if (quote != 0 || !Character.isWhitespace(x))
559: break;
560: }
561: for (;;) {
562: if (j >= str2.length()) {
563: y = 0;
564: break;
565: }
566: y = str2.charAt(j++);
567: if (quote != 0 || !Character.isWhitespace(y))
568: break;
569: }
570: if (x != y)
571: return false;
572: if (x == 0)
573: return true;
574: if (x == '\'' || x == '\"') {
575: if (quote == 0)
576: quote = x;
577: else if (x == quote)
578: quote = 0;
579: }
580: }
581: }
582:
583: private static void evalTestIdAttrs(String expr, String expected) {
584: evalTest(
585: "for $x in (" + expr + ") return (string($x/@id),';')",
586: expected);
587: }
588:
589: private static void evalNodeNames(String expr, String expected) {
590: evalTest("for $node in (" + expr
591: + ") return concat(node-name($node),';')", expected);
592: }
593:
594: public static void evalTest(String expr, String expected) {
595: Object result;
596: try {
597: result = eval(expr);
598: } catch (Throwable ex) {
599: result = ex;
600: }
601: matchTest(expr, result, expected);
602: }
603:
604: public static String toString(Object value) {
605: CharArrayOutPort wr = new CharArrayOutPort();
606: gnu.xml.XMLPrinter xp = new gnu.xml.XMLPrinter(wr);
607: xp.writeObject(value);
608: xp.close();
609: return wr.toString();
610: }
611:
612: public static void matchTest(String expr, Object returned,
613: String expected) {
614: String result;
615: Throwable throwable;
616: if (returned instanceof Throwable) {
617: if (returned instanceof WrappedException) {
618: throwable = ((WrappedException) returned)
619: .getException();
620: if (throwable != null)
621: returned = throwable;
622: }
623: throwable = (Throwable) returned;
624: // throwable.printStackTrace();
625: if (returned instanceof SyntaxException)
626: result = "*** caught SyntaxException - "
627: + ((SyntaxException) returned).getMessages()
628: .getErrors();
629: else
630: result = "*** caught " + returned.getClass().getName()
631: + " ***";
632: } else {
633: result = returned.toString();
634: throwable = null;
635: }
636:
637: boolean failureExpected = failureExpectedNext != null;
638: if (matches(expected, result)) {
639: if (failureExpected)
640: unexpectedPasses++;
641: else
642: expectedPasses++;
643: if (verbose || failureExpected)
644: System.out.println((failureExpected ? "XPASS: \""
645: : "PASS: \"")
646: + expr + "\" evaluated to \"" + result + "\"");
647: } else {
648: if (failureExpectedNext != null)
649: expectedFailures++;
650: else
651: unexpectedFailures++;
652: if (verbose || !failureExpected)
653: System.out.println((failureExpected ? "XFAIL: \""
654: : "FAIL: \"")
655: + expr
656: + "\" evaluated to \""
657: + result
658: + "\" but expected \"" + expected + "\"");
659: if (verbose && !failureExpected && throwable != null)
660: throwable.printStackTrace(System.out);
661: }
662: failureExpectedNext = null;
663: }
664:
665: public static String eval(String expr) throws Throwable {
666: CharArrayOutPort out = new CharArrayOutPort();
667: InPort in = new CharArrayInPort(expr);
668: SourceMessages messages = new SourceMessages();
669:
670: Compilation comp = interp.parse(in, messages,
671: Language.PARSE_IMMEDIATE);
672: SourceError firstError = messages.getErrors();
673: if (firstError != null)
674: return "*** syntax error - " + firstError;
675:
676: CallContext ctx = CallContext.getInstance();
677: gnu.lists.Consumer save = ctx.consumer;
678:
679: try {
680: ctx.consumer = interp.getOutputConsumer(out);
681: ModuleExp mod = comp.getModule();
682: mod.setName("atInteractiveLevel"); // FIXME
683: ModuleExp.evalModule(env, ctx, comp, null, null);
684: } finally {
685: ctx.consumer = save;
686: }
687:
688: String result = new String(out.toCharArray());
689: out.close();
690: return result;
691: }
692:
693: }
|