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