1/* 2Copyright (c) 2001-2005 World Wide Web Consortium, 3(Massachusetts Institute of Technology, European Research Consortium 4for Informatics and Mathematics, Keio University). All 5Rights Reserved. This work is distributed under the W3C(r) Software License [1] in the 6hope that it will be useful, but WITHOUT ANY WARRANTY; without even 7the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 9[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 10*/ 11 12 13 function assertSize(descr, expected, actual) { 14 var actualSize; 15 assertNotNull(descr, actual); 16 actualSize = actual.length; 17 assertEquals(descr, expected, actualSize); 18 } 19 20 function assertEqualsAutoCase(context, descr, expected, actual) { 21 if (builder.contentType == "text/html") { 22 if(context == "attribute") { 23 assertEquals(descr, expected.toLowerCase(), actual.toLowerCase()); 24 } else { 25 assertEquals(descr, expected.toUpperCase(), actual); 26 } 27 } else { 28 assertEquals(descr, expected, actual); 29 } 30 } 31 32 33 function assertEqualsCollectionAutoCase(context, descr, expected, actual) { 34 // 35 // if they aren't the same size, they aren't equal 36 assertEquals(descr, expected.length, actual.length); 37 38 // 39 // if there length is the same, then every entry in the expected list 40 // must appear once and only once in the actual list 41 var expectedLen = expected.length; 42 var expectedValue; 43 var actualLen = actual.length; 44 var i; 45 var j; 46 var matches; 47 for(i = 0; i < expectedLen; i++) { 48 matches = 0; 49 expectedValue = expected[i]; 50 for(j = 0; j < actualLen; j++) { 51 if (builder.contentType == "text/html") { 52 if (context == "attribute") { 53 if (expectedValue.toLowerCase() == actual[j].toLowerCase()) { 54 matches++; 55 } 56 } else { 57 if (expectedValue.toUpperCase() == actual[j]) { 58 matches++; 59 } 60 } 61 } else { 62 if(expectedValue == actual[j]) { 63 matches++; 64 } 65 } 66 } 67 if(matches == 0) { 68 assert(descr + ": No match found for " + expectedValue,false); 69 } 70 if(matches > 1) { 71 assert(descr + ": Multiple matches found for " + expectedValue, false); 72 } 73 } 74 } 75 76 function assertEqualsCollection(descr, expected, actual) { 77 // 78 // if they aren't the same size, they aren't equal 79 assertEquals(descr, expected.length, actual.length); 80 // 81 // if there length is the same, then every entry in the expected list 82 // must appear once and only once in the actual list 83 var expectedLen = expected.length; 84 var expectedValue; 85 var actualLen = actual.length; 86 var i; 87 var j; 88 var matches; 89 for(i = 0; i < expectedLen; i++) { 90 matches = 0; 91 expectedValue = expected[i]; 92 for(j = 0; j < actualLen; j++) { 93 if(expectedValue == actual[j]) { 94 matches++; 95 } 96 } 97 if(matches == 0) { 98 assert(descr + ": No match found for " + expectedValue,false); 99 } 100 if(matches > 1) { 101 assert(descr + ": Multiple matches found for " + expectedValue, false); 102 } 103 } 104 } 105 106 107 function assertEqualsListAutoCase(context, descr, expected, actual) { 108 var minLength = expected.length; 109 if (actual.length < minLength) { 110 minLength = actual.length; 111 } 112 // 113 for(var i = 0; i < minLength; i++) { 114 assertEqualsAutoCase(context, descr, expected[i], actual[i]); 115 } 116 // 117 // if they aren't the same size, they aren't equal 118 assertEquals(descr, expected.length, actual.length); 119 } 120 121 122 function assertEqualsList(descr, expected, actual) { 123 var minLength = expected.length; 124 if (actual.length < minLength) { 125 minLength = actual.length; 126 } 127 // 128 for(var i = 0; i < minLength; i++) { 129 if(expected[i] != actual[i]) { 130 assertEquals(descr, expected[i], actual[i]); 131 } 132 } 133 // 134 // if they aren't the same size, they aren't equal 135 assertEquals(descr, expected.length, actual.length); 136 } 137 138 function assertInstanceOf(descr, type, obj) { 139 if(type == "Attr") { 140 assertEquals(descr,2,obj.nodeType); 141 var specd = obj.specified; 142 } 143 } 144 145 function assertSame(descr, expected, actual) { 146 if(expected != actual) { 147 assertEquals(descr, expected.nodeType, actual.nodeType); 148 assertEquals(descr, expected.nodeValue, actual.nodeValue); 149 } 150 } 151 152 function assertURIEquals(assertID, scheme, path, host, file, name, query, fragment, isAbsolute, actual) { 153 // 154 // URI must be non-null 155 assertNotNull(assertID, actual); 156 157 var uri = actual; 158 159 var lastPound = actual.lastIndexOf("#"); 160 var actualFragment = ""; 161 if(lastPound != -1) { 162 // 163 // substring before pound 164 // 165 uri = actual.substring(0,lastPound); 166 actualFragment = actual.substring(lastPound+1); 167 } 168 if(fragment != null) assertEquals(assertID,fragment, actualFragment); 169 170 var lastQuestion = uri.lastIndexOf("?"); 171 var actualQuery = ""; 172 if(lastQuestion != -1) { 173 // 174 // substring before pound 175 // 176 uri = actual.substring(0,lastQuestion); 177 actualQuery = actual.substring(lastQuestion+1); 178 } 179 if(query != null) assertEquals(assertID, query, actualQuery); 180 181 var firstColon = uri.indexOf(":"); 182 var firstSlash = uri.indexOf("/"); 183 var actualPath = uri; 184 var actualScheme = ""; 185 if(firstColon != -1 && firstColon < firstSlash) { 186 actualScheme = uri.substring(0,firstColon); 187 actualPath = uri.substring(firstColon + 1); 188 } 189 190 if(scheme != null) { 191 assertEquals(assertID, scheme, actualScheme); 192 } 193 194 if(path != null) { 195 assertEquals(assertID, path, actualPath); 196 } 197 198 if(host != null) { 199 var actualHost = ""; 200 if(actualPath.substring(0,2) == "//") { 201 var termSlash = actualPath.substring(2).indexOf("/") + 2; 202 actualHost = actualPath.substring(0,termSlash); 203 } 204 assertEquals(assertID, host, actualHost); 205 } 206 207 if(file != null || name != null) { 208 var actualFile = actualPath; 209 var finalSlash = actualPath.lastIndexOf("/"); 210 if(finalSlash != -1) { 211 actualFile = actualPath.substring(finalSlash+1); 212 } 213 if (file != null) { 214 assertEquals(assertID, file, actualFile); 215 } 216 if (name != null) { 217 var actualName = actualFile; 218 var finalDot = actualFile.lastIndexOf("."); 219 if (finalDot != -1) { 220 actualName = actualName.substring(0, finalDot); 221 } 222 assertEquals(assertID, name, actualName); 223 } 224 } 225 226 if(isAbsolute != null) { 227 assertEquals(assertID, isAbsolute, actualPath.substring(0,1) == "/"); 228 } 229 } 230 231 232// size() used by assertSize element 233function size(collection) 234{ 235 return collection.length; 236} 237 238function same(expected, actual) 239{ 240 return expected === actual; 241} 242 243function equalsAutoCase(context, expected, actual) { 244 if (builder.contentType == "text/html") { 245 if (context == "attribute") { 246 return expected.toLowerCase() == actual; 247 } 248 return expected.toUpperCase() == actual; 249 } 250 return expected == actual; 251} 252 253function createTempURI(scheme) { 254 if (scheme == "http") { 255 return "http://localhost:8080/webdav/tmp" + Math.floor(Math.random() * 100000) + ".xml"; 256 } 257 return "file:///tmp/domts" + Math.floor(Math.random() * 100000) + ".xml"; 258} 259 260 261 262function EventMonitor() { 263 this.atEvents = new Array(); 264 this.bubbledEvents = new Array(); 265 this.capturedEvents = new Array(); 266 this.allEvents = new Array(); 267} 268 269EventMonitor.prototype.handleEvent = function(evt) { 270 switch(evt.eventPhase) { 271 case 1: 272 monitor.capturedEvents[monitor.capturedEvents.length] = evt; 273 break; 274 275 case 2: 276 monitor.atEvents[monitor.atEvents.length] = evt; 277 break; 278 279 case 3: 280 monitor.bubbledEvents[monitor.bubbledEvents.length] = evt; 281 break; 282 } 283 monitor.allEvents[monitor.allEvents.length] = evt; 284} 285 286function DOMErrorImpl(err) { 287 this.severity = err.severity; 288 this.message = err.message; 289 this.type = err.type; 290 this.relatedException = err.relatedException; 291 this.relatedData = err.relatedData; 292 this.location = err.location; 293} 294 295 296 297function DOMErrorMonitor() { 298 this.allErrors = new Array(); 299} 300 301DOMErrorMonitor.prototype.handleError = function(err) { 302 errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err); 303} 304 305DOMErrorMonitor.prototype.assertLowerSeverity = function(id, severity) { 306 var i; 307 for (i = 0; i < this.allErrors.length; i++) { 308 if (this.allErrors[i].severity >= severity) { 309 assertEquals(id, severity - 1, this.allErrors[i].severity); 310 } 311 } 312} 313 314function UserDataNotification(operation, key, data, src, dst) { 315 this.operation = operation; 316 this.key = key; 317 this.data = data; 318 this.src = src; 319 this.dst = dst; 320} 321 322function UserDataMonitor() { 323 this.allNotifications = new Array(); 324} 325 326UserDataMonitor.prototype.handle = function(operation, key, data, src, dst) { 327 userDataMonitor.allNotifications[userDataMonitor.allNotifications.length] = 328 new UserDataNotification(operation, key, data, src, dst); 329} 330 331 332 333function HTMLBuilder() { 334 this.contentType = "text/html"; 335 this.supportedContentTypes = [ "text/html" ]; 336 337 this.supportsAsyncChange = false; 338 this.async = false; 339 this.fixedAttributeNames = [ 340 "validating", "expandEntityReferences", "coalescing", 341 "signed", "hasNullString", "ignoringElementContentWhitespace", "namespaceAware", "ignoringComments", "schemaValidating"]; 342 343 this.fixedAttributeValues = [false, true, false, true, true , false, false, false, false ]; 344 this.configurableAttributeNames = [ ]; 345 this.configurableAttributeValues = [ ]; 346 this.initializationError = null; 347 this.initializationFatalError = null; 348 this.skipIncompatibleTests = true; 349 this.documentURLs = new Array(); 350 this.documentVarnames = new Array(); 351} 352 353HTMLBuilder.prototype.hasFeature = function(feature, version) { 354 return document.implementation.hasFeature(feature, version); 355} 356 357HTMLBuilder.prototype.getImplementation = function() { 358 return document.implementation; 359} 360 361HTMLBuilder.prototype.preload = function(frame, varname, url) { 362 var i; 363 this.documentVarnames[this.documentVarnames.length] = varname; 364 this.documentURLs[this.documentURLs.length] = url; 365 if (this.documentURLs.length > 1) { 366 // 367 // if all the urls are not the same 368 // 369 for (i = 1; i < this.documentURLs.length; i++) { 370 if (this.documentURLs[i] != this.documentURLs[0]) { 371 throw "Tests with multiple loads of different documents are not currently supported"; 372 } 373 } 374 } 375 return 1; 376} 377 378HTMLBuilder.prototype.cloneNode = function(srcNode, doc) { 379 var clone = null; 380 switch(srcNode.nodeType) { 381 // 382 // element 383 case 1: 384 clone = doc.createElement(srcNode.nodeName.toLowerCase()); 385 var attrs = srcNode.attributes; 386 for(var i = 0; i < attrs.length; i++) { 387 var srcAttr = attrs.item(i); 388 clone.setAttribute(srcAttr.nodeName, srcAttr.nodeValue); 389 } 390 var srcChild = srcNode.firstChild; 391 while(srcChild != null) { 392 var cloneChild = this.cloneNode(srcChild, doc); 393 if (cloneChild != null) { 394 clone.appendChild(cloneChild); 395 } 396 srcChild = srcChild.nextSibling; 397 } 398 break; 399 400 case 3: 401 clone = doc.createTextNode(srcNode.nodeValue); 402 break; 403 404 case 4: 405 clone = doc.createCDATASection(srcNode.nodeValue); 406 break; 407 408 case 7: 409 clone = doc.createProcessingInstruction(srcNode.nodeValue); 410 break; 411 412 case 8: 413 clone = doc.createComment(srcNode.nodeValue); 414 break; 415 } 416 return clone; 417 418} 419 420 421HTMLBuilder.prototype.load = function(frame, varname, url) { 422 if (this.documentVarnames[0] == varname) { 423 return document; 424 } 425 // 426 // 427 // not a perfect way to do this 428 // Document.cloneNode is implementation dependent but exists in L1 429 // and implemented in IE. The alternative brute force copy 430 // only works in L2 or higher implementations and can't copy 431 // entity and notation definitions, etc. 432 var clone = null; 433 try { 434 clone = document.cloneNode(true); 435 } catch(ex) { 436 } 437 if (clone == null) { 438 clone = document.implementation.createDocument( 439 document.documentElement.namespaceURI, 440 document.documentElement.nodeName, 441 null); 442 // 443 // Work-around since 444 // Safari does not create document element 445 // create document. 446 if (clone.documentElement == null) { 447 clone.appendChild(clone.createElement(document.documentElement.nodeName)); 448 } 449 var attrs = document.documentElement.attributes; 450 for(var i = 0; i < attrs.length; i++) { 451 var srcAttr = attrs.item(i); 452 clone.documentElement.setAttribute(srcAttr.nodeName, srcAttr.nodeValue); 453 } 454 455 var srcNode = document.firstChild; 456 while(srcNode != null && srcNode.nodeType != 1) { 457 if (srcNode.nodeType != 10) { 458 var cloneNode = this.cloneNode(srcNode, clone); 459 clone.insertBefore(cloneNode, clone.documentElement); 460 } 461 srcNode = srcNode.nextSibling; 462 } 463 srcNode = document.documentElement.nextSibling; 464 while(srcNode != null) { 465 var cloneNode = this.cloneNode(srcNode, clone); 466 clone.appendChild(cloneNode); 467 srcNode = srcNode.nextSibling; 468 } 469 srcNode = document.documentElement.firstChild; 470 while(srcNode != null) { 471 var cloneNode = this.cloneNode(srcNode, clone); 472 if (cloneNode != null) { 473 clone.documentElement.appendChild(cloneNode); 474 } 475 srcNode = srcNode.nextSibling; 476 } 477 } 478 return clone; 479} 480 481HTMLBuilder.prototype.getImplementationAttribute = function(attr) { 482 for (var i = 0; i < this.fixedAttributeNames.length; i++) { 483 if (this.fixedAttributeNames[i] == attr) { 484 return this.fixedAttributeValues[i]; 485 } 486 } 487 throw "Unrecognized implementation attribute: " + attr; 488} 489 490 491HTMLBuilder.prototype.setImplementationAttribute = function(attribute, value) { 492 var supported = this.getImplementationAttribute(attribute); 493 if (supported != value) { 494 this.initializationError = "HTML loader does not support " + attribute + "=" + value; 495 } 496} 497 498HTMLBuilder.prototype.canSetImplementationAttribute = function(attribute, value) { 499 var supported = this.getImplementationAttribute(attribute); 500 return (supported == value); 501} 502 503 504 505 506function createConfiguredBuilder() { 507 return new HTMLBuilder(); 508} 509 510function catchInitializationError(buildr, ex) { 511 buildr.initializationError = ex; 512 buildr.initializationFatalError = ex; 513} 514 515function toLowerArray(src) { 516 var newArray = new Array(); 517 var i; 518 for (i = 0; i < src.length; i++) { 519 newArray[i] = src[i].toLowerCase(); 520 } 521 return newArray; 522} 523 524 525function checkFeature(feature, version) 526{ 527 if (!builder.hasFeature(feature, version)) 528 { 529 // 530 // don't throw exception so that users can select to ignore the precondition 531 // 532 builder.initializationError = "builder does not support feature " + feature + " version " + version; 533 } 534} 535 536function setResult(resultType, message) { 537 var testName = getTargetURI(); 538 document.open(); 539 document.writeln("<html><head>"); 540 document.writeln("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; CHARSET=utf-8'>"); 541 document.write("<title>"); 542 document.write(testName + ":" + resultType); 543 document.write("</title></head><body><table width='100%' border='1' style='color:"); 544 if (resultType == null) { 545 document.writeln("green'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Success</td></tr>"); 546 } else { 547 if (resultType == "skip") { 548 document.writeln("blue'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Skipped</td></tr>"); 549 } else { 550 document.writeln("red'><tr><td>Test:</td><td>" + testName + "</td><td></tr><tr><td>Status:</td><td>" + resultType + "</td></tr>"); 551 } 552 } 553 if (message != null) { 554 document.writeln("<tr><td>Detail:</td><td>" + message + "</td></tr>"); 555 } 556 document.write("</table></body></html>"); 557 document.close(); 558 if (parent != window) { 559 parent.setResult(testName, resultType, message); 560 } 561} 562 563function checkInitialization(buildr, testname) { 564 return buildr.initializationError; 565} 566 567function preload(docRef, varname, href) { 568 return builder.preload(docRef, varname, href); 569} 570 571 572function load(docRef, varname, href) { 573 return builder.load(docRef, varname, href); 574} 575 576 577function getImplementationAttribute(attr) { 578 return builder.getImplementationAttribute(attr); 579} 580 581 582function setImplementationAttribute(attribute, value) { 583 builder.setImplementationAttribute(attribute, value); 584} 585 586function createXPathEvaluator(doc) { 587 try { 588 return doc.getFeature("XPath", null); 589 } 590 catch(ex) { 591 } 592 return doc; 593} 594 595 596function getImplementation() { 597 return builder.getImplementation(); 598} 599 600function assertEquals(id, expected, actual) { 601 var myActual; 602 if (expected != actual) { 603 myActual = actual; 604 if (actual == null) { 605 myActual = "null"; 606 } 607 throw "failure:" + id + ": assertEquals failed, actual " + myActual + ", expected " + expected + "."; 608 } 609} 610 611function assertNull(id, actual) { 612 if (actual != null) { 613 throw "failure:" + id + ": assertNull failed, actual " + actual; 614 } 615} 616 617 618function assertTrue(id, actual) { 619 if (!actual) { 620 throw "failure:" + id + ": assertTrue failed"; 621 } 622} 623 624 625function assertFalse(id, actual) { 626 if (actual) { 627 throw "failure:" + id + ": assertTrue failed"; 628 } 629} 630 631function assertNotNull(id, actual) { 632 if (actual == null) { 633 throw "failure:" + id + ": assertNotNull failed"; 634 } 635} 636 637function fail(id) { 638 throw "failure:" + id + ": fail"; 639} 640 641 642 643function getSuffix(contentType) { 644 switch(contentType) { 645 case "text/xml": 646 return ".xml"; 647 648 case "application/xhtml+xml": 649 return ".xhtml"; 650 651 case "image/svg+xml": 652 return ".svg"; 653 654 case "text/mathml": 655 return ".mml"; 656 } 657 return ".html"; 658} 659 660 661function getResourceURI(name, scheme, contentType) { 662 var base = document.documentURI; 663 if (base == null) { 664 base = ""; 665 } else { 666 base = base.substring(0, base.lastIndexOf('/') + 1) + "files/"; 667 } 668 return base + name + getSuffix(contentType); 669} 670 671 672 673function startTest() { 674 675// 676// WebKit modification: 18-August-2005 677// 678// Inform the test controller that this test has a text-format result and so should 679// be dumped as text, and also that the dump should not occur automatically. 680// 681if (window.layoutTestController) { 682 layoutTestController.dumpAsText(); 683 layoutTestController.waitUntilDone(); 684} 685// 686// End WebKit modification 687// 688 689 // 690 // invoke test setup 691 // 692 setUpPage(); 693 694 try { 695 runTest(); 696 if (builder.initializationError == null) { 697 setResult(null, null); 698 } else { 699 setResult("skip", builder.initializationError); 700 } 701 } catch(ex) { 702 if (typeof(ex.substring) != 'undefined' && ex.substring(0, 8) == "failure:") { 703 setResult("failure", ex.substring(8)); 704 } else { 705 setResult("error", ex); 706 } 707 } 708 709// 710// WebKit modification: 18-August-2005 711// 712// Inform the test controller that this test is complete, so it's time to dump. 713// 714 if (window.layoutTestController) { 715 layoutTestController.notifyDone(); 716 } 717// 718// End WebKit modification 719// 720 721} 722