testing/mochitest/chrome-harness.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7
michael@0 8 Components.utils.import("resource://gre/modules/NetUtil.jsm");
michael@0 9
michael@0 10 /*
michael@0 11 * getChromeURI converts a URL to a URI
michael@0 12 *
michael@0 13 * url: string of a URL (http://mochi.test/test.html)
michael@0 14 * returns: a nsiURI object representing the given URL
michael@0 15 *
michael@0 16 */
michael@0 17 function getChromeURI(url) {
michael@0 18 var ios = Components.classes["@mozilla.org/network/io-service;1"].
michael@0 19 getService(Components.interfaces.nsIIOService);
michael@0 20 return ios.newURI(url, null, null);
michael@0 21 }
michael@0 22
michael@0 23 /*
michael@0 24 * Convert a URL (string) into a nsIURI or NSIJARURI
michael@0 25 * This is intended for URL's that are on a file system
michael@0 26 * or in packaged up in an extension .jar file
michael@0 27 *
michael@0 28 * url: a string of a url on the local system(http://localhost/blah.html)
michael@0 29 */
michael@0 30 function getResolvedURI(url) {
michael@0 31 var chromeURI = getChromeURI(url);
michael@0 32 var resolvedURI = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
michael@0 33 getService(Components.interfaces.nsIChromeRegistry).
michael@0 34 convertChromeURL(chromeURI);
michael@0 35
michael@0 36 try {
michael@0 37 resolvedURI = resolvedURI.QueryInterface(Components.interfaces.nsIJARURI);
michael@0 38 } catch (ex) {} //not a jar file
michael@0 39
michael@0 40 return resolvedURI;
michael@0 41 }
michael@0 42
michael@0 43 /**
michael@0 44 * getChromeDir is intended to be called after getResolvedURI and convert
michael@0 45 * the input URI into a nsILocalFile (actually the directory containing the
michael@0 46 * file). This can be used for copying or referencing the file or extra files
michael@0 47 * required by the test. Usually we need to load a secondary html file or library
michael@0 48 * and this will give us file system access to that.
michael@0 49 *
michael@0 50 * resolvedURI: nsIURI (from getResolvedURI) that points to a file:/// url
michael@0 51 */
michael@0 52 function getChromeDir(resolvedURI) {
michael@0 53
michael@0 54 var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
michael@0 55 getService(Components.interfaces.nsIFileProtocolHandler);
michael@0 56 var chromeDir = fileHandler.getFileFromURLSpec(resolvedURI.spec);
michael@0 57 return chromeDir.parent.QueryInterface(Components.interfaces.nsILocalFile);
michael@0 58 }
michael@0 59
michael@0 60 /*
michael@0 61 * given a .jar file, we get all test files located inside the archive
michael@0 62 *
michael@0 63 * aBasePath: base URL to determine chrome location and search for tests
michael@0 64 * aTestPath: passed in testPath value from command line such as: dom/tests/mochitest
michael@0 65 * aDir: the test dir to append to the baseURL after getting a directory interface
michael@0 66 *
michael@0 67 * As a note, this is hardcoded to the .jar structure we use for mochitest.
michael@0 68 * Please don't assume this works for all jar files.
michael@0 69 */
michael@0 70 function getMochitestJarListing(aBasePath, aTestPath, aDir)
michael@0 71 {
michael@0 72 var zReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
michael@0 73 createInstance(Components.interfaces.nsIZipReader);
michael@0 74 var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
michael@0 75 getService(Components.interfaces.nsIFileProtocolHandler);
michael@0 76
michael@0 77 var fileName = fileHandler.getFileFromURLSpec(getResolvedURI(aBasePath).JARFile.spec);
michael@0 78 zReader.open(fileName);
michael@0 79 //hardcoded 'content' as that is the root dir in the mochikit.jar file
michael@0 80 var idx = aBasePath.indexOf('/content');
michael@0 81 var basePath = aBasePath.slice(0, idx);
michael@0 82
michael@0 83 var base = "content/" + aDir + "/";
michael@0 84
michael@0 85 if (aTestPath) {
michael@0 86 var extraPath = aTestPath;
michael@0 87 var pathToCheck = base + aTestPath;
michael@0 88 if (zReader.hasEntry(pathToCheck)) {
michael@0 89 var pathEntry = zReader.getEntry(pathToCheck);
michael@0 90 if (pathEntry.isDirectory) {
michael@0 91 base = pathToCheck;
michael@0 92 } else {
michael@0 93 var singleTestPath = basePath + '/' + base + aTestPath;
michael@0 94 var singleObject = {};
michael@0 95 singleObject[singleTestPath] = true;
michael@0 96 return singleObject;
michael@0 97 }
michael@0 98 }
michael@0 99 else if (zReader.hasEntry(pathToCheck + "/")) {
michael@0 100 base = pathToCheck + "/";
michael@0 101 }
michael@0 102 else {
michael@0 103 return null;
michael@0 104 }
michael@0 105 }
michael@0 106 var [links, count] = zList(base, zReader, basePath, true);
michael@0 107 return links;
michael@0 108 }
michael@0 109
michael@0 110 /*
michael@0 111 * Replicate the server.js list() function with a .jar file
michael@0 112 *
michael@0 113 * base: string value of base directory we are testing
michael@0 114 * zReader: handle to opened nsIZipReader object
michael@0 115 * recurse: true|false if we do subdirs
michael@0 116 *
michael@0 117 * returns:
michael@0 118 * [json object of {dir:{subdir:{file:true, file:true, ...}}}, count of tests]
michael@0 119 */
michael@0 120 function zList(base, zReader, baseJarName, recurse) {
michael@0 121 var dirs = zReader.findEntries(base + "*");
michael@0 122 var links = {};
michael@0 123 var count = 0;
michael@0 124 var fileArray = [];
michael@0 125
michael@0 126 while(dirs.hasMore()) {
michael@0 127 var entryName = dirs.getNext();
michael@0 128 if (entryName.substr(-1) == '/' && entryName.split('/').length == (base.split('/').length + 1) ||
michael@0 129 (entryName.substr(-1) != '/' && entryName.split('/').length == (base.split('/').length))) {
michael@0 130 fileArray.push(entryName);
michael@0 131 }
michael@0 132 }
michael@0 133 fileArray.sort();
michael@0 134 count = fileArray.length;
michael@0 135 for (var i=0; i < fileArray.length; i++) {
michael@0 136 var myFile = fileArray[i];
michael@0 137 if (myFile.substr(-1) === '/' && recurse) {
michael@0 138 var childCount = 0;
michael@0 139 [links[myFile], childCount] = zList(myFile, zReader, baseJarName, recurse);
michael@0 140 count += childCount;
michael@0 141 } else {
michael@0 142 if (myFile.indexOf("SimpleTest") == -1) {
michael@0 143 //we add the '/' so we don't try to run content/content/chrome
michael@0 144 links[baseJarName + '/' + myFile] = true;
michael@0 145 }
michael@0 146 }
michael@0 147 }
michael@0 148 return [links, count];
michael@0 149 }
michael@0 150
michael@0 151 /**
michael@0 152 * basePath: the URL base path to search from such as chrome://mochikit/content/a11y
michael@0 153 * testPath: the optional testPath passed into the test such as dom/tests/mochitest
michael@0 154 * dir: the test dir to append to the uri after getting a directory interface
michael@0 155 * srvScope: loaded javascript to server.js so we have aComponents.classesess to the list() function
michael@0 156 *
michael@0 157 * return value:
michael@0 158 * single test: [json object, path to test]
michael@0 159 * list of tests: [json object, null] <- directory [heirarchy]
michael@0 160 */
michael@0 161 function getFileListing(basePath, testPath, dir, srvScope)
michael@0 162 {
michael@0 163 var uri = getResolvedURI(basePath);
michael@0 164 var chromeDir = getChromeDir(uri);
michael@0 165 chromeDir.appendRelativePath(dir);
michael@0 166 basePath += '/' + dir;
michael@0 167
michael@0 168 if (testPath == "false" || testPath == false) {
michael@0 169 testPath = "";
michael@0 170 }
michael@0 171
michael@0 172 var ioSvc = Components.classes["@mozilla.org/network/io-service;1"].
michael@0 173 getService(Components.interfaces.nsIIOService);
michael@0 174 var testsDirURI = ioSvc.newFileURI(chromeDir);
michael@0 175 var testsDir = ioSvc.newURI(testPath, null, testsDirURI)
michael@0 176 .QueryInterface(Components.interfaces.nsIFileURL).file;
michael@0 177
michael@0 178 if (testPath != undefined) {
michael@0 179 var extraPath = testPath;
michael@0 180
michael@0 181 var fileNameRegexp = /(browser|test)_.+\.(xul|html|js)$/;
michael@0 182
michael@0 183 // Invalid testPath...
michael@0 184 if (!testsDir.exists())
michael@0 185 return null;
michael@0 186
michael@0 187 if (testsDir.isFile()) {
michael@0 188 if (fileNameRegexp.test(testsDir.leafName)) {
michael@0 189 var singlePath = basePath + '/' + testPath;
michael@0 190 var links = {};
michael@0 191 links[singlePath] = true;
michael@0 192 return links;
michael@0 193 }
michael@0 194 // We were passed a file that's not a test...
michael@0 195 return null;
michael@0 196 }
michael@0 197
michael@0 198 // otherwise, we were passed a directory of tests
michael@0 199 basePath += "/" + testPath;
michael@0 200 }
michael@0 201 var [links, count] = srvScope.list(basePath, testsDir, true);
michael@0 202 return links;
michael@0 203 }
michael@0 204
michael@0 205
michael@0 206 //used by tests to determine their directory based off window.location.path
michael@0 207 function getRootDirectory(path, chromeURI) {
michael@0 208 if (chromeURI === undefined)
michael@0 209 {
michael@0 210 chromeURI = getChromeURI(path);
michael@0 211 }
michael@0 212 var myURL = chromeURI.QueryInterface(Components.interfaces.nsIURL);
michael@0 213 var mydir = myURL.directory;
michael@0 214
michael@0 215 if (mydir.match('/$') != '/')
michael@0 216 {
michael@0 217 mydir += '/';
michael@0 218 }
michael@0 219
michael@0 220 return chromeURI.prePath + mydir;
michael@0 221 }
michael@0 222
michael@0 223 //used by tests to determine their directory based off window.location.path
michael@0 224 function getChromePrePath(path, chromeURI) {
michael@0 225
michael@0 226 if (chromeURI === undefined) {
michael@0 227 chromeURI = getChromeURI(path);
michael@0 228 }
michael@0 229
michael@0 230 return chromeURI.prePath;
michael@0 231 }
michael@0 232
michael@0 233 /*
michael@0 234 * Given a URI, return nsIJARURI or null
michael@0 235 */
michael@0 236 function getJar(uri) {
michael@0 237 var resolvedURI = getResolvedURI(uri);
michael@0 238 var jar = null;
michael@0 239 try {
michael@0 240 if (resolvedURI.JARFile) {
michael@0 241 jar = resolvedURI;
michael@0 242 }
michael@0 243 } catch (ex) {}
michael@0 244 return jar;
michael@0 245 }
michael@0 246
michael@0 247 /*
michael@0 248 * input:
michael@0 249 * jar: a nsIJARURI object with the jarfile and jarentry (path in jar file)
michael@0 250 *
michael@0 251 * output;
michael@0 252 * all files and subdirectories inside jarentry will be extracted to TmpD/mochikit.tmp
michael@0 253 * we will return the location of /TmpD/mochikit.tmp* so you can reference the files locally
michael@0 254 */
michael@0 255 function extractJarToTmp(jar) {
michael@0 256 var tmpdir = Components.classes["@mozilla.org/file/directory_service;1"]
michael@0 257 .getService(Components.interfaces.nsIProperties)
michael@0 258 .get("ProfD", Components.interfaces.nsILocalFile);
michael@0 259 tmpdir.append("mochikit.tmp");
michael@0 260 // parseInt is used because octal escape sequences cause deprecation warnings
michael@0 261 // in strict mode (which is turned on in debug builds)
michael@0 262 tmpdir.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
michael@0 263
michael@0 264 var zReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
michael@0 265 createInstance(Components.interfaces.nsIZipReader);
michael@0 266
michael@0 267 var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
michael@0 268 getService(Components.interfaces.nsIFileProtocolHandler);
michael@0 269
michael@0 270 var fileName = fileHandler.getFileFromURLSpec(jar.JARFile.spec);
michael@0 271 zReader.open(fileName);
michael@0 272
michael@0 273 //filepath represents the path in the jar file without the filename
michael@0 274 var filepath = "";
michael@0 275 var parts = jar.JAREntry.split('/');
michael@0 276 for (var i =0; i < parts.length - 1; i++) {
michael@0 277 if (parts[i] != '') {
michael@0 278 filepath += parts[i] + '/';
michael@0 279 }
michael@0 280 }
michael@0 281
michael@0 282 /* Create dir structure first, no guarantee about ordering of directories and
michael@0 283 * files returned from findEntries.
michael@0 284 */
michael@0 285 var dirs = zReader.findEntries(filepath + '*/');
michael@0 286 while (dirs.hasMore()) {
michael@0 287 var targetDir = buildRelativePath(dirs.getNext(), tmpdir, filepath);
michael@0 288 // parseInt is used because octal escape sequences cause deprecation warnings
michael@0 289 // in strict mode (which is turned on in debug builds)
michael@0 290 if (!targetDir.exists()) {
michael@0 291 targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
michael@0 292 }
michael@0 293 }
michael@0 294
michael@0 295 //now do the files
michael@0 296 var files = zReader.findEntries(filepath + "*");
michael@0 297 while (files.hasMore()) {
michael@0 298 var fname = files.getNext();
michael@0 299 if (fname.substr(-1) != '/') {
michael@0 300 var targetFile = buildRelativePath(fname, tmpdir, filepath);
michael@0 301 zReader.extract(fname, targetFile);
michael@0 302 }
michael@0 303 }
michael@0 304 return tmpdir;
michael@0 305 }
michael@0 306
michael@0 307 /*
michael@0 308 * Take a relative path from the current mochitest file
michael@0 309 * and returns the absolute path for the given test data file.
michael@0 310 */
michael@0 311 function getTestFilePath(path) {
michael@0 312 if (path[0] == "/") {
michael@0 313 throw new Error("getTestFilePath only accepts relative path");
michael@0 314 }
michael@0 315 // Get the chrome/jar uri for the current mochitest file
michael@0 316 // gTestPath being defined by the test harness in browser-chrome tests
michael@0 317 // or window is being used for mochitest-browser
michael@0 318 var baseURI = typeof(gTestPath) == "string" ? gTestPath : window.location.href;
michael@0 319 var parentURI = getResolvedURI(getRootDirectory(baseURI));
michael@0 320 var file;
michael@0 321 if (parentURI.JARFile) {
michael@0 322 // If it's a jar/zip, we have to extract it first
michael@0 323 file = extractJarToTmp(parentURI);
michael@0 324 } else {
michael@0 325 // Otherwise, we can directly cast it to a file URI
michael@0 326 var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
michael@0 327 getService(Components.interfaces.nsIFileProtocolHandler);
michael@0 328 file = fileHandler.getFileFromURLSpec(parentURI.spec);
michael@0 329 }
michael@0 330 // Then walk by the given relative path
michael@0 331 path.split("/")
michael@0 332 .forEach(function (p) {
michael@0 333 if (p == "..") {
michael@0 334 file = file.parent;
michael@0 335 } else if (p != ".") {
michael@0 336 file.append(p);
michael@0 337 }
michael@0 338 });
michael@0 339 return file.path;
michael@0 340 }
michael@0 341
michael@0 342 /*
michael@0 343 * Simple utility function to take the directory structure in jarentryname and
michael@0 344 * translate that to a path of a nsILocalFile.
michael@0 345 */
michael@0 346 function buildRelativePath(jarentryname, destdir, basepath)
michael@0 347 {
michael@0 348 var baseParts = basepath.split('/');
michael@0 349 if (baseParts[baseParts.length-1] == '') {
michael@0 350 baseParts.pop();
michael@0 351 }
michael@0 352
michael@0 353 var parts = jarentryname.split('/');
michael@0 354
michael@0 355 var targetFile = Components.classes["@mozilla.org/file/local;1"]
michael@0 356 .createInstance(Components.interfaces.nsILocalFile);
michael@0 357 targetFile.initWithFile(destdir);
michael@0 358
michael@0 359 for (var i = baseParts.length; i < parts.length; i++) {
michael@0 360 targetFile.append(parts[i]);
michael@0 361 }
michael@0 362
michael@0 363 return targetFile;
michael@0 364 }
michael@0 365
michael@0 366 function readConfig(filename) {
michael@0 367 filename = filename || "testConfig.js";
michael@0 368
michael@0 369 var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].
michael@0 370 getService(Components.interfaces.nsIProperties);
michael@0 371 var configFile = fileLocator.get("ProfD", Components.interfaces.nsIFile);
michael@0 372 configFile.append(filename);
michael@0 373
michael@0 374 if (!configFile.exists())
michael@0 375 return {};
michael@0 376
michael@0 377 var fileInStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
michael@0 378 createInstance(Components.interfaces.nsIFileInputStream);
michael@0 379 fileInStream.init(configFile, -1, 0, 0);
michael@0 380
michael@0 381 var str = NetUtil.readInputStreamToString(fileInStream, fileInStream.available());
michael@0 382 fileInStream.close();
michael@0 383 return JSON.parse(str);
michael@0 384 }
michael@0 385
michael@0 386 function registerTests() {
michael@0 387 var testsURI = Components.classes["@mozilla.org/file/directory_service;1"].
michael@0 388 getService(Components.interfaces.nsIProperties).
michael@0 389 get("ProfD", Components.interfaces.nsILocalFile);
michael@0 390 testsURI.append("tests.manifest");
michael@0 391 var ioSvc = Components.classes["@mozilla.org/network/io-service;1"].
michael@0 392 getService(Components.interfaces.nsIIOService);
michael@0 393 var manifestFile = ioSvc.newFileURI(testsURI).
michael@0 394 QueryInterface(Components.interfaces.nsIFileURL).file;
michael@0 395
michael@0 396 Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).
michael@0 397 autoRegister(manifestFile);
michael@0 398 }
michael@0 399
michael@0 400 function getTestList(params, callback) {
michael@0 401 registerTests();
michael@0 402
michael@0 403 var baseurl = 'chrome://mochitests/content';
michael@0 404 if (window.parseQueryString) {
michael@0 405 params = parseQueryString(location.search.substring(1), true);
michael@0 406 }
michael@0 407 if (!params.baseurl) {
michael@0 408 params.baseurl = baseurl;
michael@0 409 }
michael@0 410
michael@0 411 var config = readConfig();
michael@0 412 for (var p in params) {
michael@0 413 if (params[p] == 1) {
michael@0 414 config[p] = true;
michael@0 415 } else if (params[p] == 0) {
michael@0 416 config[p] = false;
michael@0 417 } else {
michael@0 418 config[p] = params[p];
michael@0 419 }
michael@0 420 }
michael@0 421 params = config;
michael@0 422 if (params.manifestFile) {
michael@0 423 getTestManifest("http://mochi.test:8888/" + params.manifestFile, params, callback);
michael@0 424 return;
michael@0 425 }
michael@0 426
michael@0 427 var links = {};
michael@0 428 // load server.js in so we can share template functions
michael@0 429 var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
michael@0 430 getService(Ci.mozIJSSubScriptLoader);
michael@0 431 var srvScope = {};
michael@0 432 scriptLoader.loadSubScript('chrome://mochikit/content/server.js',
michael@0 433 srvScope);
michael@0 434
michael@0 435 if (getResolvedURI(baseurl).JARFile) {
michael@0 436 links = getMochitestJarListing(baseurl, params.testPath, params.testRoot);
michael@0 437 } else {
michael@0 438 links = getFileListing(baseurl, params.testPath, params.testRoot, srvScope);
michael@0 439 }
michael@0 440 callback(links);
michael@0 441 }

mercurial