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 ; 13 import gnu.xquery.util.NodeUtils; 14 15 16 17 public class RunXQTS extends FilterConsumer 18 { 19 static XQuery xqueryLanguage = XQuery.getInstance(); 20 21 22 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 34 ModuleManager manager = ModuleManager.getInstance(); 35 Object failExpected; 36 37 boolean verbose = true; 38 boolean useComments = true; 39 40 String directory; 41 String catalog; 42 String XQTSVersion; 43 String ResultOffsetPath; 44 String XQueryQueryOffsetPath; 45 String XQueryXQueryOffsetPath; 46 String XQueryFileExtension; 47 String XQueryXFileExtension; 48 String compare; 49 Object contextItem; 50 51 int passCount; 52 int xpassCount; 53 int failCount; 54 int xfailCount; 55 int cannotTellCount; 56 57 58 StringBuffer expectedErrorsBuf = new StringBuffer ("|"); 59 60 String expectedErrors; 61 62 String logFileName = "XQTS.log"; 63 XMLPrinter xqlog; 64 65 String collectionID; 66 Values collectionDocuments; 67 68 private void summaryReport (int count, String 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 XQTS_RESULT_NAMESPACE 87 = "http://www.w3.org/2005/02/query-test-XQTSResult"; 88 89 static Object 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 testRunGroupType 101 = Symbol.make(XQTS_RESULT_NAMESPACE, "test-run", ""); 102 static Object testSuiteGroupType 103 = Symbol.make(XQTS_RESULT_NAMESPACE, "test-suite", ""); 104 static Object testCaseGroupType 105 = Symbol.make(XQTS_RESULT_NAMESPACE, "test-case", ""); 106 107 private void writeBeginGroup (String name) 108 { 109 xqlog.beginGroup(Symbol.make(XQTS_RESULT_NAMESPACE, name, "")); 110 } 111 112 private void writeBeginAttribute (String name) 113 { 114 xqlog.beginAttribute(name); 115 } 116 117 private void writeAttribute (String name, String value) 118 { 119 writeBeginAttribute(name); 120 xqlog.write(value); 121 xqlog.endAttribute(); 122 } 123 124 private void writeQexoAttribute (String name, String 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 name, String value) 133 { 134 if (useComments) 135 { 136 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 [] 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 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 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 currentElementType; 190 Symbol currentElementSymbol; 191 192 194 Stack elementTypeStack = new Stack(); 195 196 boolean inStartTag; 197 int attrValueStart; 198 int[] elementStartIndex = new int[20]; 200 AttributesImpl attributes = new AttributesImpl (); 201 202 String query = null; 203 String 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 224 expectFailures("surrogates12|surrogates13|surrogates14|surrogates15", 225 "surrogates not handled by java.util.regex"); 226 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 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 262 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 "regex range subtraction not implemented"); 284 } 285 286 private void expectFailures (String testNames, String reason) 287 { 288 while (testNames != null) 289 { 290 int dot = testNames.indexOf('|'); 291 String 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 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 336 nesting++; 337 } 338 339 boolean tagMatches (String localName) 340 { 341 if (localName.equals(currentElementSymbol.getLocalName())) 342 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 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 sbuf = new StringBuffer (); 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 ID = attributes.getValue("ID"); 411 String filename = attributes.getValue("FileName"); 412 sources.put(ID, filename); 413 } 414 else if (testName == null && tagMatches("module")) 415 { 416 String ID = attributes.getValue("ID"); 417 String 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 testName; 430 String scenario; 431 String testQueryName; 432 String testFilePath; 433 String testQuery; 434 435 int maxTests = -1; 436 437 void report (String result, String 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 sbuf = new StringBuffer ("(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 testName) 482 throws Throwable 483 { 484 failExpected = expectedFailures.get(testName); 485 if (failExpected == null) 486 { 487 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 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 ex) 504 { 505 String xfilename = directory + '/' + XQueryXQueryOffsetPath 506 + testFilePath + testQueryName + XQueryXFileExtension; 507 if (new java.io.File (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 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: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 ex) 600 { 601 if (ex instanceof NumberFormatException 602 && expectedErrors.indexOf("|FORG0001|") >= 0) 603 report("pass", "caught NumberFormatException expected:"+expectedErrors); 604 else if (ex instanceof ClassCastException 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 actual = new String (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 expected = null; 653 for (int ialt = 0; ialt < numOutputFileAlts; ialt++) 654 { 655 String 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 (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 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 arg1 , 731 String arg2 , 732 String 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 786 789 Stack attrs1 = new Stack(); 790 Stack attrs2 = new Stack(); 791 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 attr1 = arg1.substring(i1, end1); 799 attrs1.push(attr1); 800 String 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 for (int i = attrs1.size(); --i >= 0; ) 829 { 830 String attr1 = (String ) attrs1.elementAt(i); 831 for (int j = attrs2.size(); ; ) 832 { 833 if (--j < 0) 834 return false; 835 String attr2 = (String ) 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 word1 = arg1.substring(start1, end1); 861 String 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 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 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 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 selectedTest; 943 944 public String 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); if (selectedTest == null 957 || selectedTest.equals(testName)) 958 { 959 xqlog.beginGroup(testCaseGroupType); 960 writeAttribute("name", testName); 961 try 962 { 963 evalTest(testName); 965 } 966 catch (Throwable 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 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 variable = attributes.getValue("variable"); 989 Symbol symbol = Symbol.parse(variable); 990 String name = attributes.getValue("name"); 991 String filename 992 = directory + '/' + XQueryQueryOffsetPath + testFilePath 993 + name + XQueryFileExtension; 994 InPort in; 995 try 996 { 997 in = InPort.openFile(filename); 998 Object 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 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 inputFile = getElementValue(); 1015 if ("userdefined".equals(inputFile)) 1017 inputFile = "emptydoc"; 1018 String path = directory + '/' + sources.get(inputFile); 1019 1020 String 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 { 1030 variable = null; 1031 symbol = null; 1032 } 1033 try 1034 { 1035 Object 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 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 inputFile = getElementValue(); 1053 String variable = attributes.getValue("variable"); 1054 Object inputValue = sources.get(inputFile); 1055 String 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 inputFile = getElementValue(); 1065 Object inputValue = sources.get(inputFile); 1066 Object 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 inputName = getElementValue(); 1079 String path = "file://" + directory + '/' + sources.get(inputName); 1080 if (collectionID == null) 1081 throw new Error ("<input-document> not in <collection>"); 1082 try 1083 { 1084 KDocument value = (KDocument) Document.parseCached(path); 1085 collectionDocuments.writeObject(value); 1086 } 1087 catch (Throwable 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 uri = attributes.getValue("namespace"); 1108 String module = getElementValue(); 1109 String mfile = (String ) modules.get(module); 1110 String mpath = directory + '/' + mfile + XQueryFileExtension; 1111 String 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 1137 cout.setLength(elementStartIndex[nesting]); 1138 nesting--; 1139 Object type = elementTypeStack.pop(); 1140 currentElementType = type; 1141 currentElementSymbol = type instanceof Symbol ? (Symbol) type : null; 1142 } 1143 1144 public void beginAttribute(Object attrType) 1145 { 1146 super.beginAttribute(attrType); 1147 attrValueStart = cout.length(); 1148 } 1149 1150 public void endAttribute() 1151 { 1152 super.endAttribute(); 1153 String attrValue = cout.toSubString(attrValueStart, cout.length()-1); 1154 Symbol sym = (Symbol) attributeType; 1155 String uri = sym.getNamespaceURI(); 1156 String local = sym.getLocalPart(); 1157 String prefix = sym.getPrefix(); 1158 String 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 |