KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > xquery > testsuite > RunXQTS


1 package gnu.xquery.testsuite;
2 import java.io.*;
3 import java.util.*;
4 import gnu.lists.*;
5 import gnu.text.*;
6 import gnu.mapping.*;
7 import gnu.expr.*;
8 import gnu.xml.*;
9 import gnu.kawa.xml.*;
10 import gnu.mapping.Symbol;
11 import gnu.xquery.lang.*;
12 import org.xml.sax.helpers.AttributesImpl JavaDoc;
13 import gnu.xquery.util.NodeUtils;
14
15 /** Run a suite of XQuery tests, as read from an xml file. */
16
17 public class RunXQTS extends FilterConsumer
18 {
19   static XQuery xqueryLanguage = XQuery.getInstance();
20
21   /* #ifdef JAVA5 */
22   // HashMap<String,String> expectedFailures = new HashMap<String,String>();
23
// HashMap<String,String> modules = new HashMap<String,String>();
24
// HashMap<String,Object> sources = new HashMap<String,Object>();
25
// Stack<Symbol> externalVariablesSet = new Stack<Symbol>();
26
// Stack<String> outputFileAlts = new Stack<String>();
27
/* #else */
28   Hashtable expectedFailures = new Hashtable();
29   Hashtable modules = new Hashtable();
30   Hashtable sources = new Hashtable();
31   Stack externalVariablesSet = new Stack();
32   Stack outputFileAlts = new Stack();
33   /* #endif */
34   ModuleManager manager = ModuleManager.getInstance();
35   Object JavaDoc failExpected;
36
37   boolean verbose = true;
38   boolean useComments = true;
39
40   String JavaDoc directory;
41   String JavaDoc catalog;
42   String JavaDoc XQTSVersion;
43   String JavaDoc ResultOffsetPath;
44   String JavaDoc XQueryQueryOffsetPath;
45   String JavaDoc XQueryXQueryOffsetPath;
46   String JavaDoc XQueryFileExtension;
47   String JavaDoc XQueryXFileExtension;
48   String JavaDoc compare;
49   Object JavaDoc contextItem;
50
51   int passCount;
52   int xpassCount;
53   int failCount;
54   int xfailCount;
55   int cannotTellCount;
56
57   /** Set of expected error codes. The format is "|Error1}...|ErrorN|". */
58   StringBuffer JavaDoc expectedErrorsBuf = new StringBuffer JavaDoc("|");
59   /** Same as expectedErrorBuf.toString() after collecting expected-errors. */
60   String JavaDoc expectedErrors;
61
62   String JavaDoc logFileName = "XQTS.log";
63   XMLPrinter xqlog;
64
65   String JavaDoc collectionID;
66   Values collectionDocuments;
67
68   private void summaryReport (int count, String JavaDoc label)
69   {
70     if (count > 0)
71       {
72         System.out.print(label);
73         System.out.println(count);
74       }
75   }
76
77   private void summaryReport ()
78   {
79     summaryReport(passCount, "# of expected passes ");
80     summaryReport(xfailCount, "# of expected failures ");
81     summaryReport(xpassCount, "# of unexpected successes ");
82     summaryReport(failCount, "# of unexpected failures ");
83     summaryReport(cannotTellCount, "# of cannot-tell (Inspect) results ");
84   }
85
86   public static final String JavaDoc XQTS_RESULT_NAMESPACE
87   = "http://www.w3.org/2005/02/query-test-XQTSResult";
88
89   static Object JavaDoc testSuiteResultGroupType;
90   static
91   {
92     NamespaceBinding namespaceNodes
93       = new NamespaceBinding(null, XQTS_RESULT_NAMESPACE,
94             new NamespaceBinding("q",
95                                  XQuery.QEXO_FUNCTION_NAMESPACE,
96                                  NamespaceBinding.predefinedXML));
97     Symbol sym = Symbol.make(XQTS_RESULT_NAMESPACE, "test-suite-result", "");
98     testSuiteResultGroupType = new XName(sym, namespaceNodes);
99   }
100   static Object JavaDoc testRunGroupType
101     = Symbol.make(XQTS_RESULT_NAMESPACE, "test-run", "");
102   static Object JavaDoc testSuiteGroupType
103     = Symbol.make(XQTS_RESULT_NAMESPACE, "test-suite", "");
104   static Object JavaDoc testCaseGroupType
105     = Symbol.make(XQTS_RESULT_NAMESPACE, "test-case", "");
106
107   private void writeBeginGroup (String JavaDoc name)
108   {
109     xqlog.beginGroup(Symbol.make(XQTS_RESULT_NAMESPACE, name, ""));
110   }
111
112   private void writeBeginAttribute (String JavaDoc name)
113   {
114     xqlog.beginAttribute(name);
115   }
116
117   private void writeAttribute (String JavaDoc name, String JavaDoc value)
118   {
119     writeBeginAttribute(name);
120     xqlog.write(value);
121     xqlog.endAttribute();
122   }
123
124   private void writeQexoAttribute (String JavaDoc name, String JavaDoc value)
125   {
126     xqlog.beginAttribute(Symbol.make(XQuery.QEXO_FUNCTION_NAMESPACE,
127                                      name, "q"));
128     xqlog.write(value);
129     xqlog.endAttribute();
130   }
131
132   private void writeVerbose (String JavaDoc name, String JavaDoc value)
133   {
134     if (useComments)
135       {
136         // The tricky part is to make sure that the result can be validated.
137
// Specifically, no spaces are allowed in a <test-case>.
138
xqlog.printIndent = -1;
139         xqlog.beginComment();
140         xqlog.printIndent = 0;
141         xqlog.writeBreakFill();
142         xqlog.write(name); xqlog.write(": ");
143         xqlog.write(value);
144         xqlog.writeBreakFill();
145         xqlog.endComment();
146       }
147     else
148       writeQexoAttribute(name, value);
149   }
150
151   public static void main (String JavaDoc[] args)
152   {
153     gnu.xquery.lang.XQuery.registerEnvironment();
154     Language.requirePedantic = true;
155     for (int i = 0; i < args.length; i++)
156       {
157     try
158       {
159             RunXQTS runner = new RunXQTS(new CharArrayOutPort());
160             runner.directory = args[i];
161             runner.catalog = runner.directory + "/XQTSCatalog.xml";
162             System.err.println("catalog: "+runner.catalog);
163             XMLPrinter xqlog
164               = new XMLPrinter(new BufferedOutputStream(new FileOutputStream(runner.logFileName)),
165                                runner.logFileName);
166             runner.xqlog = xqlog;
167             xqlog.setPrintXMLdecl(true);
168             xqlog.setStyle("xml");
169             xqlog.useEmptyElementTag = 1;
170             Object JavaDoc saveIndent = XMLPrinter.indentLoc.get(null);
171             XMLPrinter.indentLoc.set("pretty");
172             xqlog.beginDocument();
173             XMLPrinter.indentLoc.set(saveIndent);
174
175         Document.parse(runner.catalog, runner);
176             xqlog.endDocument();
177             runner.summaryReport();
178             xqlog.close();
179       }
180     catch (Throwable JavaDoc ex)
181       {
182             ex.printStackTrace();
183         System.err.println("caught "+ex+" while processing "+args[i]);
184       }
185       }
186   }
187
188   int nesting = 0;
189   Object JavaDoc currentElementType;
190   Symbol currentElementSymbol;
191   /* #ifdef JAVA5 */
192   // Stack<Object> elementTypeStack = new Stack<Object>();
193
/* #else */
194   Stack elementTypeStack = new Stack();
195   /* #endif */
196   boolean inStartTag;
197   int attrValueStart;
198   // Start in cout's buffer of current element, indexed by nesting level.
199
int[] elementStartIndex = new int[20];
200   AttributesImpl JavaDoc attributes = new AttributesImpl JavaDoc();
201
202   String JavaDoc query = null;
203   String JavaDoc expect = null;
204
205   CharArrayOutPort cout;
206
207   public RunXQTS(CharArrayOutPort out)
208   {
209     super(out);
210     this.cout = out;
211
212     expectFailures("K-ReplaceFunc-8", "allow bad regex replacement string");
213     expectFailures("trivial-1|trivial-2|trivial-3|trivial-4",
214                    "testsuite error - bug 3974");
215     expectFailures("Constr-namespace-13", "testsuite error? missing namespace undeclaration");
216     expectFailures("static-context-1", "unchecked unknownType in element(*,TypeName)");
217     expectFailures("NodTest003", "actually pass? different char encoding");
218     expectFailures("K-FunctionProlog-11|K-FunctionProlog-41",
219                    "item() is treated as equivalent to item()*");
220     expectFailures("ForExprType030|ForExprType033|LocalNameFromQNameFunc005|"
221                    +"CastAs671|CastAs672",
222                    "xs:normalizedString, xs:NCName, xs:ENTITY not implemented");
223     /* #ifndef JAVA5 */
224     expectFailures("surrogates12|surrogates13|surrogates14|surrogates15",
225                    "surrogates not handled by java.util.regex");
226     /* #endif */
227     expectFailures("K-SeqExprInstanceOf-53", "too lenient about non-stanadrd types: void");
228     expectFailures("ST-Axes001|ST-Axes002|ST-Axes003|ST-Axes004|ST-Axes005|"
229                    +"ST-Axes006|ST-Axes007|ST-Axes008|ST-Axes009|ST-Axes010|"
230                    +"ST-Axes011|ST-Axes012|ST-Axes013|ST-Axes014|ST-Axes015",
231                    "depends on static typing feature");
232     expectFailures("fn-id-dtd-5|fn-id-dtd-7|fn-id-dtd-8|fn-id-dtd-9|"
233                    +"fn-id-dtd-12|fn-id-dtd-13|fn-id-dtd-15|fn-id-dtd-16|"
234                    +"fn-id-dtd-17|fn-id-dtd-18|fn-id-dtd-19|"
235                    +"fn-id-dtd-20|fn-id-dtd-21|fn-id-dtd-23|",
236                    "fn:id only works with xml:id so far");
237     expectFailures("fn-idref-dtd-5|fn-idref-dtd-7|fn-idref-dtd-8|"
238                    +"fn-idref-dtd-9|fn-idref-dtd-12|fn-idref-dtd-13|"
239                    +"fn-idref-dtd-14|fn-idref-dtd-15|fn-idref-dtd-16|"
240                    +"fn-idref-dtd-17|fn-idref-dtd-18|fn-idref-dtd-19|"
241                    +"fn-idref-dtd-20|fn-idref-dtd-21|fn-idref-dtd-23|",
242                    "fn:idref doesn't do much yet");
243     /* #ifndef use:java.text.Normalizer */
244     expectFailures("fn-normalize-unicode1args-1|"
245                    +"fn-normalize-unicode1args-2|"
246                    +"fn-normalize-unicode1args-3|"
247                    +"fn-normalize-unicode1args-4|"
248                    +"fn-normalize-unicode1args-5|"
249                    +"fn-normalize-unicode1args-6|"
250                    +"fn-normalize-unicode2args-1|"
251                    +"fn-normalize-unicode2args-2|"
252                    +"fn-normalize-unicode2args-3|"
253                    +"fn-normalize-unicode-1|"
254                    +"fn-normalize-unicode-3|fn-normalize-unicode-4|"
255                    +"fn-normalize-unicode-5|fn-normalize-unicode-6|"
256                    +"fn-normalize-unicode-7|K-NormalizeUnicodeFunc-4|"
257                    +"K-NormalizeUnicodeFunc-5|K-NormalizeUnicodeFunc-6|"
258                    +"K-NormalizeUnicodeFunc-7|K-NormalizeUnicodeFunc-8|"
259                    +"K-NormalizeUnicodeFunc-11|K-NormalizeUnicodeFunc-12",
260                    "fn:normalize-unicode not unimplemented yet");
261     /* #endif */
262     // RunXQTS failures rather than Qexo errors:
263
// Some work under gcj but not JDK 1.4.x or 1.5.0_05:
264
expectFailures("vardeclerr|K-InternalVariablesWith-17|K-InternalVariablesWith-18",
265                    "missing check for circular definitions");
266     expectFailures("K-TimeAddDTD-1|K-TimeAddDTD-2|K-TimeSubtractDTD-1",
267                    "bad interaction between fields and millis");
268     expectFailures("op-time-greater-than-2",
269                    "comparing xs:time doesn't handle differing timezones");
270     expectFailures("K-SubstringBeforeFunc-5|K-SubstringAfterFunc-5|"
271                    +"K-ContainsFunc-5|K-StartsWithFunc-5|K-EndsWithFunc-5",
272                    "some string functions don't support collation argument");
273     expectFailures("K-CodepointToStringFunc-8|K-CodepointToStringFunc-11|"
274                    +"K-CodepointToStringFunc-12|K-CodepointToStringFunc-14|"
275                    +"K-CodepointToStringFunc-15",
276                    "test-case excessively strict about disallowed characetrs");
277     expectFailures("caselessmatch04",
278                    "regex/unicode special case");
279     expectFailures("string-queries-results-q4|K2-FunctionProlog-7",
280                    "function conversion incorrect for user-defined functions");
281     expectFailures("caselessmatch10|caselessmatch11",
282                    // Need to translate [xxx-[yyy]] to [xxx&&[^yyy]].
283
"regex range subtraction not implemented");
284   }
285
286   private void expectFailures (String JavaDoc testNames, String JavaDoc reason)
287   {
288     while (testNames != null)
289       {
290         int dot = testNames.indexOf('|');
291         String JavaDoc testName;
292         if (dot >= 0)
293           {
294             testName = testNames.substring(0, dot);
295             testNames = testNames.substring(dot+1);
296           }
297         else
298           {
299             testName = testNames;
300             testNames = null;
301           }
302         if (testName.length() > 0)
303           expectedFailures.put(testName, reason);
304       }
305   }
306
307   public void beginGroup(Object JavaDoc type)
308   {
309     if (inStartTag)
310       handleStartTag();
311     attributes.clear();
312     inStartTag = true;
313     elementTypeStack.push(currentElementType);
314     currentElementType = type;
315     currentElementSymbol = type instanceof Symbol ? (Symbol) type : null;
316     /*
317     System.err.println("beginGroup "+typeName);
318     if ("test-suite".equals(typeName) && nesting == 0)
319       inTestSuite = true;
320     else if ("test-group".equals(typeName))
321       {
322       }
323     else if ("test".equals(typeName)
324     && (nesting == 0 || (inTestSuite && nesting == 1)))
325       inTest = true;
326     else if (inTestSuite ? nesting == 2 : nesting == 1)
327       {
328     cout.setLength(0);
329     currentTag = typeName;
330       }
331     else if (currentTag == null)
332       throw new RuntimeException("saw <"+typeName+"> not in <test>");
333     else
334       base.beginGroup(type);
335     */

336     nesting++;
337   }
338
339   boolean tagMatches (String JavaDoc localName)
340   {
341     if (localName.equals(currentElementSymbol.getLocalName()))
342       // also check uri FIXME
343
return true;
344     return false;
345   }
346
347   public void handleStartTag ()
348   {
349     elementStartIndex[nesting] = cout.length();
350     if (tagMatches("test-suite"))
351       {
352         XQueryQueryOffsetPath = attributes.getValue("XQueryQueryOffsetPath");
353         XQueryXQueryOffsetPath = attributes.getValue("XQueryXQueryOffsetPath");
354         XQueryFileExtension = attributes.getValue("XQueryFileExtension");
355         XQueryXFileExtension = attributes.getValue("XQueryXFileExtension");
356         ResultOffsetPath = attributes.getValue("ResultOffsetPath");
357         XQTSVersion = attributes.getValue("version");
358  
359         xqlog.beginGroup(testSuiteResultGroupType);
360         writeBeginGroup("implementation");
361         writeAttribute("name", "Qexo");
362         writeAttribute("version", kawa.Version.getVersion());
363         writeBeginGroup("organization");
364         writeAttribute("name", "GNU / Per Bothner");
365         xqlog.endGroup();
366         writeBeginGroup("submittor");
367         String JavaDoc user = System.getProperty("user.name");
368         if ("bothner".equals(user))
369           {
370             writeAttribute("name", "Per Bothner");
371             writeAttribute("email", "per@bothner.com");
372           }
373         else
374           writeAttribute("name", user);
375         xqlog.endGroup();
376         xqlog.endGroup();
377         writeBeginGroup("syntax");
378         xqlog.write("XQuery");
379         xqlog.endGroup();
380         xqlog.beginGroup(testRunGroupType);
381         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
382         gnu.kawa.xml.XTimeType.dateTimeType.now().toStringDate(sbuf);
383         writeAttribute("dateRun", sbuf.toString());
384         xqlog.beginGroup(testSuiteGroupType);
385         writeAttribute("version", XQTSVersion);
386         xqlog.endGroup();
387         xqlog.endGroup();
388
389       }
390     else if (tagMatches("test-group"))
391       {
392         xqlog.writeComment("test-group "+attributes.getValue("name"));
393       }
394     else if (tagMatches("test-case"))
395       {
396         testName = attributes.getValue("name");
397         scenario = attributes.getValue("scenario");
398         testFilePath = attributes.getValue("FilePath");
399         testQueryName = null;
400         outputFileAlts.clear();
401         expectedErrorsBuf.setLength(1);
402         manager.clear();
403       }
404     else if (tagMatches("query"))
405       {
406         testQueryName = attributes.getValue("name");
407       }
408     else if (tagMatches("source"))
409       {
410         String JavaDoc ID = attributes.getValue("ID");
411         String JavaDoc filename = attributes.getValue("FileName");
412         sources.put(ID, filename);
413       }
414     else if (testName == null && tagMatches("module"))
415       {
416         String JavaDoc ID = attributes.getValue("ID");
417         String JavaDoc filename = attributes.getValue("FileName");
418         modules.put(ID, filename);
419       }
420     else if (tagMatches("collection"))
421       {
422         collectionID = attributes.getValue("ID");
423         collectionDocuments = new Values();
424         sources.put(collectionID, collectionDocuments);
425       }
426     inStartTag = false;
427   }
428
429   String JavaDoc testName;
430   String JavaDoc scenario;
431   String JavaDoc testQueryName;
432   String JavaDoc testFilePath;
433   String JavaDoc testQuery;
434
435   int maxTests = -1;
436
437   void report (String JavaDoc result, String JavaDoc comment)
438   {
439     boolean failed = "fail".equals(result);
440     if (failExpected == null)
441       {
442         if (failed)
443           {
444             System.out.println("FAIL: "+testName);
445             failCount++;
446           }
447         else if ("cannot tell".equals(result))
448           cannotTellCount++;
449         else
450           passCount++;
451       }
452     else
453       {
454         if (failed)
455           xfailCount++;
456         else
457           {
458             System.out.println("XPASS: "+testName);
459             xpassCount++;
460           }
461       }
462
463     writeAttribute("result", result);
464
465     if (failed && failExpected != null)
466       {
467         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc("(expected-to-fail: ");
468         sbuf.append(failExpected.toString());
469         sbuf.append(')');
470         if (comment != null)
471           {
472             sbuf.append("; ");
473             sbuf.append(comment);
474           }
475         comment = sbuf.toString();
476       }
477     if (comment != null)
478       writeAttribute("comment", comment);
479   }
480
481   public void evalTest (String JavaDoc testName)
482     throws Throwable JavaDoc
483   {
484     failExpected = expectedFailures.get(testName);
485     if (failExpected == null)
486       {
487         // Check for a wildcard: replace a final non-negative integer by '*'.
488
int len = testName.length();
489         while (--len > 0 && Character.digit(testName.charAt(len), 10) >= 0);
490         failExpected = expectedFailures.get(testName.substring(0, len+1)+'*');
491       }
492     Environment env = Environment.getCurrent();
493     SourceMessages messages = new SourceMessages();
494     String JavaDoc filename
495       = directory + '/' + XQueryQueryOffsetPath + testFilePath
496       + testQueryName + XQueryFileExtension;
497     InPort in;
498     expectedErrors = expectedErrorsBuf.toString();
499     try
500       {
501         in = InPort.openFile(filename);
502       }
503     catch (java.io.FileNotFoundException JavaDoc ex)
504       {
505         String JavaDoc xfilename = directory + '/' + XQueryXQueryOffsetPath
506           + testFilePath + testQueryName + XQueryXFileExtension;
507         if (new java.io.File JavaDoc(xfilename).exists())
508           {
509             report("fail", "xqueryx not implemented");
510             return;
511           }
512         throw ex;
513       }
514     Compilation comp;
515     Procedure withContextProc = null;
516     try
517       {
518         if (contextItem != null)
519           {
520             withContextProc = xqueryLanguage.evalToFocusProc(in, messages);
521             comp = null;
522           }
523         else
524           comp = xqueryLanguage.parse(in, messages, Language.PARSE_IMMEDIATE);
525         if (messages.seenErrors())
526           throw new SyntaxException(messages);
527       }
528     catch (SyntaxException ex)
529       {
530         in.close();
531         SourceError error = messages.getErrors();
532         String JavaDoc errorString = error == null ? "" : "|" + error.code + "|";
533         if (expectedErrors.indexOf(errorString) >= 0)
534           {
535             report("pass", null);
536           }
537         else if (errorString.equals("|XQST0009|"))
538           {
539
540             if (failExpected == null)
541               failExpected = "'import schema' not implemented";
542             report("fail", null);
543           }
544         else if (error.message != null
545                  && error.message.indexOf("unknown type xs:NOTATION") >= 0
546                  && (expectedErrors.equals("|XPST0080|")
547                      || expectedErrors.equals("|XPST0017|")))
548           {
549             report("fail", null);
550           }
551         else if (error.message != null
552                  && error.message.indexOf("unknown type xs:ENTITY") >= 0
553                  && (expectedErrors.equals("|XPTY0004|")))
554           {
555             report("fail", null);
556           }
557         else if (error.message != null
558                  && error.message.indexOf("unknown function") >= 0
559                  && (expectedErrors.equals("|XPDY0002|")
560                      || expectedErrors.equals("|XPTY0004|")
561                      || expectedErrors.equals("|XQDY0025|")
562                      || expectedErrors.equals("|FODC0001|")
563                      || (expectedErrors.equals("|XPST0017|")
564                          && (// error.message.endsWith(" fn:collection") ||
565
error.message.endsWith(" fn:id")
566                              || error.message.endsWith(" fn:idref")))))
567
568           {
569             report("fail", null);
570           }
571         else if (expectedErrors.length() > 1)
572           report("pass", "static error: "+error+" expected:"+expectedErrors);
573         else
574           report("fail", "static error: "+error.message);
575         return;
576       }
577     in.close();
578
579     CallContext ctx = CallContext.getInstance();
580     if (contextItem != null)
581       {
582     gnu.math.IntNum one = gnu.math.IntNum.one();
583         withContextProc.check3(contextItem, one, one, ctx);
584       }
585     gnu.lists.Consumer save = ctx.consumer;
586     CharArrayOutPort out = new CharArrayOutPort();
587     XMLPrinter xout = new XMLPrinter(out, false);
588     xout.useEmptyElementTag = 1;
589     xout.escapeNonAscii = false;
590     xout.canonicalizeCDATA = true;
591     ctx.consumer = xout;
592     try
593       {
594         if (contextItem != null)
595           ctx.runUntilDone();
596         else
597           ModuleExp.evalModule(env, ctx, comp, null, null);
598       }
599     catch (Throwable JavaDoc ex)
600       {
601         if (ex instanceof NumberFormatException JavaDoc
602             && expectedErrors.indexOf("|FORG0001|") >= 0)
603           report("pass", "caught NumberFormatException expected:"+expectedErrors);
604         else if (ex instanceof ClassCastException JavaDoc
605                  && (expectedErrors.indexOf("|XPTY0004|") >= 0
606                      || expectedErrors.indexOf("|XPTY0020|") >= 0
607                      || expectedErrors.indexOf("|FORG0001|") >= 0
608                      || expectedErrors.indexOf("|FOAR0002|") >= 0))
609           report("pass", "caught ClassCastException expected:"+expectedErrors);
610         else if (expectedErrors.length() > 1)
611           report("pass", "caught "+ex+" expected:"+expectedErrors);
612         else
613           {
614             report("fail", "caught "+ex);
615             if (verbose)
616               {
617                 CharArrayWriter wr = new CharArrayWriter();
618                 PrintWriter pr = new PrintWriter(wr);
619                 ex.printStackTrace(pr);
620                 pr.flush();
621                 writeVerbose("stack", wr.toString());
622                 wr.close();
623               }
624           }
625         return;
626       }
627
628     if (messages.seenErrors())
629       {
630         if (expectedErrors.length() > 1)
631           report("pass", "error: "+messages.getErrors()+" expected: "+expectedErrors);
632         else
633           report("fail", "error: "+messages.getErrors());
634         return;
635       }
636
637     if ("trivial".equals(scenario))
638       {
639         failExpected = "trivial embedding not implemented";
640         report("fail", null);
641         return;
642       }
643
644     String JavaDoc actual = new String JavaDoc(out.toCharArray());
645     byte[] expectedBytes = new byte[1024];
646     xout.close();
647     ctx.consumer = save;
648     
649     int numOutputFileAlts = outputFileAlts.size();
650     boolean foundMatchingOutput = false;
651     boolean displayDifference = false;
652     String JavaDoc expected = null;
653     for (int ialt = 0; ialt < numOutputFileAlts; ialt++)
654       {
655         String JavaDoc outname = directory + '/' + ResultOffsetPath + testFilePath
656           + outputFileAlts.elementAt(ialt);
657         FileInputStream expectStream = new FileInputStream(outname);
658         int expectedLength = 0;
659         for (;;)
660           {
661             int avail = expectedBytes.length-expectedLength;
662             if (avail < 1024)
663               {
664                 byte[] tmp = new byte[2*expectedBytes.length];
665                 System.arraycopy(expectedBytes, 0, tmp, 0, expectedLength);
666                 expectedBytes = tmp;
667               }
668             int n = expectStream.read(expectedBytes, expectedLength, avail);
669             if (n < 0)
670               break;
671             expectedLength += n;
672           }
673         expectStream.close();
674         expected = new String JavaDoc(expectedBytes, 0, expectedLength, "UTF-8");
675         expected = expected.replaceAll("\r", "");
676         actual = actual.replaceAll("\r", "");
677         boolean matches = matches(actual, expected, compare);
678         if (matches)
679           {
680             report("pass", null);
681             foundMatchingOutput = true;
682             break;
683           }
684         else if ("Inspect".equals(compare))
685           {
686             report("cannot tell", null);
687             foundMatchingOutput = true;
688             displayDifference = verbose;
689             break;
690           }
691       }
692
693     if (! foundMatchingOutput)
694       {
695         if (expectedErrors.length() > 1)
696           {
697             report("fail", "expected error: "+expectedErrors);
698             return;
699           }
700         else
701           {
702             report("fail", null);
703             if (verbose && expectedFailures.get(testName) == null)
704               displayDifference = true;
705           }
706       }
707     if (displayDifference)
708       {
709         writeVerbose("compare", compare);
710         writeVerbose("expected", expected);
711         writeVerbose("actual", actual);
712       }
713   }
714
715   private static int grabAttribute (String JavaDoc str, int start)
716   {
717     char inAttr = 0;
718     for (int i = start; ; )
719       {
720         if (i >= str.length())
721           return -1;
722         char ch = str.charAt(i++);
723         if (inAttr == 0 && (ch == '\"' || ch == '\''))
724           inAttr = ch;
725         else if (ch == inAttr)
726           return i;
727       }
728   }
729
730   public static boolean matches (String JavaDoc arg1 /* result */,
731                                  String JavaDoc arg2 /*expected*/,
732                                  String JavaDoc compare)
733   {
734     int len1 = arg1.length();
735     int len2 = arg2.length();
736     int i1 = 0, i2 = 0;
737     boolean intag = false;
738     int start_attr1 = 0;
739     int start_attr2 = 0;
740     boolean isXML = "XML".equals(compare) || "Fragment".equals(compare);
741     char inAttr = 0;
742     for (;;)
743       {
744         if (i1 == len1 && i2 == len2)
745           return true;
746         int c1 = i1 == len1 ? -1 : arg1.charAt(i1);
747         int c2 = i2 == len2 ? -1 : arg2.charAt(i2);
748         if (c1 == c2)
749           {
750             if (c1 == '<' && isXML)
751               {
752                 intag = true;
753                 start_attr1 = 0;
754                 start_attr2 = 0;
755                 inAttr = 0;
756               }
757             else if (intag && c1 == '>')
758               {
759                 intag = false;
760               }
761             else if (intag && Character.isWhitespace((char) c1)
762                      && inAttr == 0)
763
764               {
765                 start_attr1 = i1+1;
766                 start_attr2 = i2+1;;
767               }
768             else if (intag && inAttr == 0 && (c1 == '"' || c1 == '\''))
769               {
770                 inAttr = (char) c1;
771               }
772             else if (intag && inAttr == c1)
773               {
774                 start_attr1 = 0;
775                 start_attr2 = 0;
776                 inAttr = 0;
777               }
778             i1++;
779             i2++;
780           }
781         else if (intag && start_attr1 > 0)
782           {
783             i1 = start_attr1;
784             i2 = start_attr2;
785             /* #ifdef JAVA5 */
786             // Stack<String> attrs1 = new Stack<String>();
787
// Stack<String> attrs2 = new Stack<String>();
788
/* #else */
789             Stack attrs1 = new Stack();
790             Stack attrs2 = new Stack();
791             /* #endif */
792             for (;;)
793               {
794                 int end1 = grabAttribute(arg1, i1);
795                 int end2 = grabAttribute(arg2, i2);
796                 if (end1 < 0 || end2 < 0)
797                   return false;
798                 String JavaDoc attr1 = arg1.substring(i1, end1);
799                 attrs1.push(attr1);
800                 String JavaDoc attr2 = arg2.substring(i2, end2);
801                 attrs2.push(attr2);
802                 i1 = end1;
803                 i2 = end2;
804                 for (;;)
805                   {
806                     if (i1 >= len1) return false;
807                     c1 = arg1.charAt(i1++);
808                     if (! Character.isWhitespace((char) c1))
809                       break; }
810                 for (;;)
811                   {
812                     if (i2 >= len2) return false;
813                     c2 = arg2.charAt(i2++);
814                     if (! Character.isWhitespace((char) c2))
815                       break;
816                   }
817                 boolean done1 = c1 == '/' || c1 == '>';
818                 boolean done2 = c2 == '/' || c2 == '>';
819                 if (done1 && done2)
820                   break;
821                 if (done1 || done2)
822                   return false;
823                 i1--;
824                 i2--;
825               }
826             // Same number of attributes.
827
// Do an O(n^2) search to make sure the sets are equal.
828
for (int i = attrs1.size(); --i >= 0; )
829               {
830                 String JavaDoc attr1 = (String JavaDoc) attrs1.elementAt(i);
831                 for (int j = attrs2.size(); ; )
832                   {
833                     if (--j < 0)
834                       return false;
835                     String JavaDoc attr2 = (String JavaDoc) attrs2.elementAt(j);
836                     if (attr1.equals(attr2))
837                       break;
838                   }
839               }
840             start_attr1 = 0;
841             start_attr2 = 0;
842             intag = false;
843           }
844         else if (isFloatChar(c1)
845                  ? (isFloatChar(c2) || (i2 > 0 && isFloatChar(arg2.charAt(i2-1))))
846                  : (isFloatChar(c2) && (i1 > 0 && isFloatChar(arg1.charAt(i1-1)))))
847           {
848             int start1 = i1, start2 = i2;
849             while (start1 > 0 && isFloatChar(arg1.charAt(start1-1)))
850               start1--;
851             while (start2 > 0 && isFloatChar(arg2.charAt(start2-1)))
852               start2--;
853             int end1 = i1, end2 = i2;
854             while (end1 < len1 && isFloatChar(arg1.charAt(end1)))
855               end1++;
856             while (end2 < len2 && isFloatChar(arg2.charAt(end2)))
857               end2++;
858             if (end1 <= start1 || end2 <= start2)
859               return false;
860             String JavaDoc word1 = arg1.substring(start1, end1);
861             String JavaDoc word2 = arg2.substring(start2, end2);
862             try
863               {
864                 float f1 = Float.parseFloat(word1);
865                 float f2 = Float.parseFloat(word2);
866                 if (Float.floatToIntBits(f1) != Float.floatToIntBits(f2))
867                   return false;
868               }
869             catch (Throwable JavaDoc ex)
870               {
871                 return false;
872               }
873             i1 = end1;
874             i2 = end2;
875           }
876         else if (isXML && (c1 == ' ' || c1 == '\n' || c1 == '\t' || c1 == '\r'))
877           {
878             i1++;
879           }
880         else if (isXML && (c2 == ' ' || c2 == '\n' || c2 == '\t' || c2 == '\r'))
881           {
882             i2++;
883           }
884         // If isXML, then "/>" matches "></ANYNAME>".
885
else if (isXML && c1 == '/' && c2 == '>'
886                  && i1 + 1 < len1 && i2 + 2 < len2
887                  && arg1.charAt(i1+1) == '>'
888                  && arg2.charAt(i2+1) == '<'
889                  && arg2.charAt(i2+2) == '/')
890           {
891             for (i2 = i2 + 3; ; i2++)
892               {
893                 if (i2 >= len2)
894                   return false;
895                 char c = arg2.charAt(i2);
896                 if (c == '>')
897                   break;
898                 if (! XName.isNamePart(c))
899                   return false;
900               }
901             i1 = i1 + 2;
902             i2 = i2 + 1;
903           }
904         else if (c2 == '&' && i2 + 2 < len2
905                  && arg2.charAt(i2+1) == '#')
906           {
907             if (c1 >= 0xD800 && c1 < 0xDC00 && i1 + 1 < len1)
908               c1 = (c1 - 0xD800) * 0x400
909                   + (arg1.charAt(++i1) - 0xDC00) + 0x10000;
910             i2 = i2 + 2;
911             int base = 10;
912             if (arg2.charAt(i2) == 'x')
913               {
914                 i2++;
915                 base = 16;
916               }
917             int semi = arg2.indexOf(';', i2);
918             try
919               {
920                 c2 = Integer.parseInt(arg2.substring(i2, semi), base);
921               }
922             catch (Throwable JavaDoc ex)
923               {
924                 return false;
925               }
926             i1 = i1 + 1;
927             i2 = semi+1;
928             if (c1 != c2)
929               return false;
930           }
931         else
932           return false;
933       }
934   }
935
936   static boolean isFloatChar (int c)
937   {
938     return (c >= '0' && c <= '9')
939       || c == '.' || c == '-' || c == '+' || c == 'E';
940   }
941
942   String JavaDoc selectedTest;
943
944   public String JavaDoc getElementValue ()
945   {
946     return cout.toSubString(elementStartIndex[nesting]);
947   }
948
949   public void endGroup()
950   {
951     if (inStartTag)
952       handleStartTag();
953     if (tagMatches("test-case"))
954       {
955         if (--maxTests == 0) System.exit(0); // FIXME
956
if (selectedTest == null
957             || selectedTest.equals(testName))
958           {
959             xqlog.beginGroup(testCaseGroupType);
960             writeAttribute("name", testName);
961             try
962               {
963                 // Other attributes and <test-case> body written by evalTest.
964
evalTest(testName);
965               }
966             catch (Throwable JavaDoc ex)
967               {
968                 System.err.println("test-case name:"+testName);
969                 System.err.println("caught "+ex);
970                 ex.printStackTrace();
971               }
972             xqlog.endGroup();
973           }
974         //xqlog.flush();
975
testName = null;
976         contextItem = null;
977         Environment env = Environment.getCurrent();
978         while (! externalVariablesSet.empty())
979           env.remove((Symbol) externalVariablesSet.pop());
980       }
981     else if (tagMatches("expected-error"))
982       {
983         expectedErrorsBuf.append(getElementValue());
984         expectedErrorsBuf.append('|');
985       }
986     else if (tagMatches("input-query"))
987       {
988         String JavaDoc variable = attributes.getValue("variable");
989         Symbol symbol = Symbol.parse(variable);
990         String JavaDoc name = attributes.getValue("name");
991         String JavaDoc filename
992           = directory + '/' + XQueryQueryOffsetPath + testFilePath
993           + name + XQueryFileExtension;
994         InPort in;
995         try
996           {
997             in = InPort.openFile(filename);
998             Object JavaDoc value = XQuery.getInstance().eval(in);
999             in.close();
1000            Environment current = Environment.getCurrent();
1001            current.put(symbol, null, value);
1002            externalVariablesSet.push(symbol);
1003          }
1004        catch (Throwable JavaDoc ex)
1005          {
1006            System.err.println("input-query: cannot open "+filename);
1007            System.err.println("caught "+ex);
1008            ex.printStackTrace();
1009            System.exit(-1);
1010          }
1011      }
1012    else if (tagMatches("input-file") || tagMatches("contextItem"))
1013      {
1014        String JavaDoc inputFile = getElementValue();
1015        // KLUDGE around testsuite bug!
1016
if ("userdefined".equals(inputFile))
1017          inputFile = "emptydoc";
1018        String JavaDoc path = directory + '/' + sources.get(inputFile);
1019
1020        String JavaDoc variable;
1021        Symbol symbol;
1022        if (tagMatches("input-file"))
1023          {
1024            variable = attributes.getValue("variable");
1025            symbol = Symbol.parse(variable);
1026            externalVariablesSet.push(symbol);
1027         }
1028        else // tagMatches("contextItem")
1029
{
1030            variable = null;
1031            symbol = null;
1032          }
1033        try
1034          {
1035            Object JavaDoc value = gnu.kawa.xml.Document.parseCached(path);
1036            if (symbol != null)
1037              Environment.getCurrent().put(symbol, null, value);
1038            else
1039              contextItem = value;
1040          }
1041        catch (Throwable JavaDoc ex)
1042          {
1043            System.err.println("caught "+ex);
1044            System.err.println("reading data file "+path);
1045            System.err.println("inputFile:"+inputFile+" variable:"+variable+" path:"+path);
1046            ex.printStackTrace();
1047            System.exit(-1);
1048          }
1049      }
1050    else if (tagMatches("input-URI"))
1051      {
1052        String JavaDoc inputFile = getElementValue();
1053        String JavaDoc variable = attributes.getValue("variable");
1054        Object JavaDoc inputValue = sources.get(inputFile);
1055        String JavaDoc path = inputValue instanceof Values ? "collection:"+inputFile
1056          : "file://" + directory + '/' + inputValue;
1057        Symbol symbol = Symbol.parse(variable);
1058        externalVariablesSet.push(symbol);
1059        Environment.getCurrent().put(symbol, null,
1060                                     gnu.kawa.xml.XDataType.toURI(path));
1061      }
1062    else if (tagMatches("defaultCollection"))
1063      {
1064        String JavaDoc inputFile = getElementValue();
1065        Object JavaDoc inputValue = sources.get(inputFile);
1066        Object JavaDoc val = NodeUtils.getSavedCollection("collection:"+inputFile);
1067        NodeUtils.setSavedCollection("#default", val);
1068      }
1069    else if (tagMatches("collection"))
1070      {
1071        NodeUtils.setSavedCollection("collection:"+collectionID,
1072                                     collectionDocuments.canonicalize());
1073        collectionID = null;
1074        collectionDocuments = null;
1075      }
1076    else if (tagMatches("input-document"))
1077      {
1078        String JavaDoc inputName = getElementValue();
1079        String JavaDoc path = "file://" + directory + '/' + sources.get(inputName);
1080        if (collectionID == null)
1081          throw new Error JavaDoc("<input-document> not in <collection>");
1082        try
1083          {
1084            KDocument value = (KDocument) Document.parseCached(path);
1085            collectionDocuments.writeObject(value);
1086          }
1087         catch (Throwable JavaDoc ex)
1088          {
1089            System.err.println("caught "+ex);
1090            System.err.println("reading data file "+path);
1091            System.err.println("for collection "+collectionID);
1092            ex.printStackTrace();
1093            System.exit(-1);
1094          }
1095      }
1096    else if (tagMatches("output-file"))
1097      {
1098        outputFileAlts.push(getElementValue());
1099        compare = attributes.getValue("compare");
1100      }
1101    else if (tagMatches("test-suite"))
1102      {
1103        xqlog.endGroup();
1104      }
1105    else if (testName != null && tagMatches("module"))
1106      {
1107        String JavaDoc uri = attributes.getValue("namespace");
1108        String JavaDoc module = getElementValue();
1109        String JavaDoc mfile = (String JavaDoc) modules.get(module);
1110        String JavaDoc mpath = directory + '/' + mfile + XQueryFileExtension;
1111        String JavaDoc mclass = Compilation.mangleURI(uri)
1112          + '.' + XQuery.makeClassName(mpath);
1113
1114        ModuleInfo minfo = manager.findWithClassName(mclass);
1115        minfo.sourcePath = mfile + XQueryFileExtension;
1116        minfo.sourceAbsPath = mpath;
1117        minfo.setNamespaceUri(uri);
1118      }
1119    /*
1120    else if ("test".equals(typeName)
1121    && (nesting == 0 || (inTestSuite && nesting == 1)))
1122      {
1123    inTest = false;
1124    TestMisc.evalTest(query, expect);
1125      }
1126    else if (inTestSuite ? nesting == 2 : nesting == 1)
1127      {
1128    if ("query".equals(typeName))
1129      query = sout.toString();
1130    else if ("expect".equals(typeName))
1131      expect = sout.toString();
1132    currentTag = null;
1133      }
1134    else
1135      base.endGroup();
1136    */

1137    cout.setLength(elementStartIndex[nesting]);
1138    nesting--;
1139    Object JavaDoc type = elementTypeStack.pop();
1140    currentElementType = type;
1141    currentElementSymbol = type instanceof Symbol ? (Symbol) type : null;
1142  }
1143
1144  public void beginAttribute(Object JavaDoc attrType)
1145  {
1146    super.beginAttribute(attrType);
1147    attrValueStart = cout.length();
1148  }
1149
1150  public void endAttribute()
1151  {
1152    super.endAttribute();
1153    String JavaDoc attrValue = cout.toSubString(attrValueStart, cout.length()-1);
1154    Symbol sym = (Symbol) attributeType;
1155    String JavaDoc uri = sym.getNamespaceURI();
1156    String JavaDoc local = sym.getLocalPart();
1157    String JavaDoc prefix = sym.getPrefix();
1158    String JavaDoc qname = (prefix == null || prefix.length() == 0 ? local
1159                    : prefix+":"+local);
1160    cout.setLength(attrValueStart);
1161    attributes.addAttribute(uri, local, qname, "CDATA", attrValue);
1162  }
1163
1164  public void beforeContent ()
1165  {
1166    if (! inAttribute && inStartTag)
1167      handleStartTag();
1168  }
1169}
1170
Popular Tags