Home | History | Annotate | Download | only in core
      1 /*
      2 Copyright (c) 2001-2005 World Wide Web Consortium,
      3 (Massachusetts Institute of Technology, European Research Consortium
      4 for Informatics and Mathematics, Keio University). All
      5 Rights Reserved. This work is distributed under the W3C(r) Software License [1] in the
      6 hope that it will be useful, but WITHOUT ANY WARRANTY; without even
      7 the 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
    233 function size(collection)
    234 {
    235   return collection.length;
    236 }
    237 
    238 function same(expected, actual)
    239 {
    240   return expected === actual;
    241 }
    242 
    243 function 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 
    253 function 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 
    262 function EventMonitor() {
    263   this.atEvents = new Array();
    264   this.bubbledEvents = new Array();
    265   this.capturedEvents = new Array();
    266   this.allEvents = new Array();
    267 }
    268 
    269 EventMonitor.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 
    286 function 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 
    297 function DOMErrorMonitor() {
    298   this.allErrors = new Array();
    299 }
    300 
    301 DOMErrorMonitor.prototype.handleError = function(err) {
    302     errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err);
    303 }
    304 
    305 DOMErrorMonitor.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 
    314 function 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 
    322 function UserDataMonitor() {
    323 	this.allNotifications = new Array();
    324 }
    325 
    326 UserDataMonitor.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 
    333 function 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 
    353 HTMLBuilder.prototype.hasFeature = function(feature, version) {
    354     return document.implementation.hasFeature(feature, version);
    355 }
    356 
    357 HTMLBuilder.prototype.getImplementation = function() {
    358   return document.implementation;
    359 }
    360 
    361 HTMLBuilder.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 
    378 HTMLBuilder.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 
    421 HTMLBuilder.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 
    481 HTMLBuilder.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 
    491 HTMLBuilder.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 
    498 HTMLBuilder.prototype.canSetImplementationAttribute = function(attribute, value) {
    499     var supported = this.getImplementationAttribute(attribute);
    500     return (supported == value);
    501 }
    502 
    503 
    504 
    505 
    506 function createConfiguredBuilder() {
    507     return new HTMLBuilder();
    508 }
    509 
    510 function catchInitializationError(buildr, ex) {
    511    buildr.initializationError = ex;
    512    buildr.initializationFatalError = ex;
    513 }
    514 
    515 function 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 
    525 function 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 
    536 function 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 
    563 function checkInitialization(buildr, testname) {
    564    return buildr.initializationError;
    565 }
    566 
    567 function preload(docRef, varname, href) {
    568    return builder.preload(docRef, varname, href);
    569 }
    570 
    571 
    572 function load(docRef, varname, href) {
    573    return builder.load(docRef, varname, href);
    574 }
    575 
    576 
    577 function getImplementationAttribute(attr) {
    578     return builder.getImplementationAttribute(attr);
    579 }
    580 
    581 
    582 function setImplementationAttribute(attribute, value) {
    583     builder.setImplementationAttribute(attribute, value);
    584 }
    585 
    586 function createXPathEvaluator(doc) {
    587     try {
    588         return doc.getFeature("XPath", null);
    589     }
    590     catch(ex) {
    591     }
    592     return doc;
    593 }
    594 
    595 
    596 function getImplementation() {
    597     return builder.getImplementation();
    598 }
    599 
    600 function 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 
    611 function assertNull(id, actual) {
    612    if (actual != null) {
    613        throw "failure:" + id + ": assertNull failed, actual " + actual;
    614    }
    615 }
    616 
    617 
    618 function assertTrue(id, actual) {
    619    if (!actual) {
    620        throw "failure:" + id + ": assertTrue failed";
    621    }
    622 }
    623 
    624 
    625 function assertFalse(id, actual) {
    626    if (actual) {
    627        throw "failure:" + id +  ": assertTrue failed";
    628    }
    629 }
    630 
    631 function assertNotNull(id, actual) {
    632    if (actual == null) {
    633        throw "failure:" + id + ": assertNotNull failed";
    634    }
    635 }
    636 
    637 function fail(id) {
    638     throw "failure:" + id +  ": fail";
    639 }
    640 
    641 
    642 
    643 function 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 
    661 function 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 
    673 function 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 //
    681 if (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