gecko-dev/testing/mochitest/chrome-harness.js
Jim Blandy 7e20285e70 Bug 914753: Make Emacs file variable header lines correct, or at least consistent. DONTBUILD r=ehsan
The -*- file variable lines -*- establish per-file settings that Emacs will
pick up. This patch makes the following changes to those lines (and touches
nothing else):

 - Never set the buffer's mode.

   Years ago, Emacs did not have a good JavaScript mode, so it made sense
   to use Java or C++ mode in .js files. However, Emacs has had js-mode for
   years now; it's perfectly serviceable, and is available and enabled by
   default in all major Emacs packagings.

   Selecting a mode in the -*- file variable line -*- is almost always the
   wrong thing to do anyway. It overrides Emacs's default choice, which is
   (now) reasonable; and even worse, it overrides settings the user might
   have made in their '.emacs' file for that file extension. It's only
   useful when there's something specific about that particular file that
   makes a particular mode appropriate.

 - Correctly propagate settings that establish the correct indentation
   level for this file: c-basic-offset and js2-basic-offset should be
   js-indent-level. Whatever value they're given should be preserved;
   different parts of our tree use different indentation styles.

 - We don't use tabs in Mozilla JS code. Always set indent-tabs-mode: nil.
   Remove tab-width: settings, at least in files that don't contain tab
   characters.

 - Remove js2-mode settings that belong in the user's .emacs file, like
   js2-skip-preprocessor-directives.
2014-06-24 22:12:07 -07:00

443 lines
14 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/NetUtil.jsm");
/*
* getChromeURI converts a URL to a URI
*
* url: string of a URL (http://mochi.test/test.html)
* returns: a nsiURI object representing the given URL
*
*/
function getChromeURI(url) {
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
return ios.newURI(url, null, null);
}
/*
* Convert a URL (string) into a nsIURI or NSIJARURI
* This is intended for URL's that are on a file system
* or in packaged up in an extension .jar file
*
* url: a string of a url on the local system(http://localhost/blah.html)
*/
function getResolvedURI(url) {
var chromeURI = getChromeURI(url);
var resolvedURI = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
getService(Components.interfaces.nsIChromeRegistry).
convertChromeURL(chromeURI);
try {
resolvedURI = resolvedURI.QueryInterface(Components.interfaces.nsIJARURI);
} catch (ex) {} //not a jar file
return resolvedURI;
}
/**
* getChromeDir is intended to be called after getResolvedURI and convert
* the input URI into a nsILocalFile (actually the directory containing the
* file). This can be used for copying or referencing the file or extra files
* required by the test. Usually we need to load a secondary html file or library
* and this will give us file system access to that.
*
* resolvedURI: nsIURI (from getResolvedURI) that points to a file:/// url
*/
function getChromeDir(resolvedURI) {
var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
getService(Components.interfaces.nsIFileProtocolHandler);
var chromeDir = fileHandler.getFileFromURLSpec(resolvedURI.spec);
return chromeDir.parent.QueryInterface(Components.interfaces.nsILocalFile);
}
/*
* given a .jar file, we get all test files located inside the archive
*
* aBasePath: base URL to determine chrome location and search for tests
* aTestPath: passed in testPath value from command line such as: dom/tests/mochitest
* aDir: the test dir to append to the baseURL after getting a directory interface
*
* As a note, this is hardcoded to the .jar structure we use for mochitest.
* Please don't assume this works for all jar files.
*/
function getMochitestJarListing(aBasePath, aTestPath, aDir)
{
var zReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
createInstance(Components.interfaces.nsIZipReader);
var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
getService(Components.interfaces.nsIFileProtocolHandler);
var fileName = fileHandler.getFileFromURLSpec(getResolvedURI(aBasePath).JARFile.spec);
zReader.open(fileName);
//hardcoded 'content' as that is the root dir in the mochikit.jar file
var idx = aBasePath.indexOf('/content');
var basePath = aBasePath.slice(0, idx);
var base = "content/" + aDir + "/";
if (aTestPath) {
var extraPath = aTestPath;
var pathToCheck = base + aTestPath;
if (zReader.hasEntry(pathToCheck)) {
var pathEntry = zReader.getEntry(pathToCheck);
if (pathEntry.isDirectory) {
base = pathToCheck;
} else {
var singleTestPath = basePath + '/' + base + aTestPath;
var singleObject = {};
singleObject[singleTestPath] = true;
return singleObject;
}
}
else if (zReader.hasEntry(pathToCheck + "/")) {
base = pathToCheck + "/";
}
else {
return null;
}
}
var [links, count] = zList(base, zReader, basePath, true);
return links;
}
/*
* Replicate the server.js list() function with a .jar file
*
* base: string value of base directory we are testing
* zReader: handle to opened nsIZipReader object
* recurse: true|false if we do subdirs
*
* returns:
* [json object of {dir:{subdir:{file:true, file:true, ...}}}, count of tests]
*/
function zList(base, zReader, baseJarName, recurse) {
var dirs = zReader.findEntries(base + "*");
var links = {};
var count = 0;
var fileArray = [];
while(dirs.hasMore()) {
var entryName = dirs.getNext();
if (entryName.substr(-1) == '/' && entryName.split('/').length == (base.split('/').length + 1) ||
(entryName.substr(-1) != '/' && entryName.split('/').length == (base.split('/').length))) {
fileArray.push(entryName);
}
}
fileArray.sort();
count = fileArray.length;
for (var i=0; i < fileArray.length; i++) {
var myFile = fileArray[i];
if (myFile.substr(-1) === '/' && recurse) {
var childCount = 0;
[links[myFile], childCount] = zList(myFile, zReader, baseJarName, recurse);
count += childCount;
} else {
if (myFile.indexOf("SimpleTest") == -1) {
//we add the '/' so we don't try to run content/content/chrome
links[baseJarName + '/' + myFile] = true;
}
}
}
return [links, count];
}
/**
* basePath: the URL base path to search from such as chrome://mochikit/content/a11y
* testPath: the optional testPath passed into the test such as dom/tests/mochitest
* dir: the test dir to append to the uri after getting a directory interface
* srvScope: loaded javascript to server.js so we have aComponents.classesess to the list() function
*
* return value:
* single test: [json object, path to test]
* list of tests: [json object, null] <- directory [heirarchy]
*/
function getFileListing(basePath, testPath, dir, srvScope)
{
var uri = getResolvedURI(basePath);
var chromeDir = getChromeDir(uri);
chromeDir.appendRelativePath(dir);
basePath += '/' + dir.replace(/\\/g, '/');
if (testPath == "false" || testPath == false) {
testPath = "";
}
testPath = testPath.replace(/\\\\/g, '\\').replace(/\\/g, '/');
var ioSvc = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var testsDirURI = ioSvc.newFileURI(chromeDir);
var testsDir = ioSvc.newURI(testPath, null, testsDirURI)
.QueryInterface(Components.interfaces.nsIFileURL).file;
if (testPath != undefined) {
var extraPath = testPath;
var fileNameRegexp = /(browser|test)_.+\.(xul|html|js)$/;
// Invalid testPath...
if (!testsDir.exists())
return null;
if (testsDir.isFile()) {
if (fileNameRegexp.test(testsDir.leafName)) {
var singlePath = basePath + '/' + testPath;
var links = {};
links[singlePath] = true;
return links;
}
// We were passed a file that's not a test...
return null;
}
// otherwise, we were passed a directory of tests
basePath += "/" + testPath;
}
var [links, count] = srvScope.list(basePath, testsDir, true);
return links;
}
//used by tests to determine their directory based off window.location.path
function getRootDirectory(path, chromeURI) {
if (chromeURI === undefined)
{
chromeURI = getChromeURI(path);
}
var myURL = chromeURI.QueryInterface(Components.interfaces.nsIURL);
var mydir = myURL.directory;
if (mydir.match('/$') != '/')
{
mydir += '/';
}
return chromeURI.prePath + mydir;
}
//used by tests to determine their directory based off window.location.path
function getChromePrePath(path, chromeURI) {
if (chromeURI === undefined) {
chromeURI = getChromeURI(path);
}
return chromeURI.prePath;
}
/*
* Given a URI, return nsIJARURI or null
*/
function getJar(uri) {
var resolvedURI = getResolvedURI(uri);
var jar = null;
try {
if (resolvedURI.JARFile) {
jar = resolvedURI;
}
} catch (ex) {}
return jar;
}
/*
* input:
* jar: a nsIJARURI object with the jarfile and jarentry (path in jar file)
*
* output;
* all files and subdirectories inside jarentry will be extracted to TmpD/mochikit.tmp
* we will return the location of /TmpD/mochikit.tmp* so you can reference the files locally
*/
function extractJarToTmp(jar) {
var tmpdir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
tmpdir.append("mochikit.tmp");
// parseInt is used because octal escape sequences cause deprecation warnings
// in strict mode (which is turned on in debug builds)
tmpdir.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
var zReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
createInstance(Components.interfaces.nsIZipReader);
var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
getService(Components.interfaces.nsIFileProtocolHandler);
var fileName = fileHandler.getFileFromURLSpec(jar.JARFile.spec);
zReader.open(fileName);
//filepath represents the path in the jar file without the filename
var filepath = "";
var parts = jar.JAREntry.split('/');
for (var i =0; i < parts.length - 1; i++) {
if (parts[i] != '') {
filepath += parts[i] + '/';
}
}
/* Create dir structure first, no guarantee about ordering of directories and
* files returned from findEntries.
*/
var dirs = zReader.findEntries(filepath + '*/');
while (dirs.hasMore()) {
var targetDir = buildRelativePath(dirs.getNext(), tmpdir, filepath);
// parseInt is used because octal escape sequences cause deprecation warnings
// in strict mode (which is turned on in debug builds)
if (!targetDir.exists()) {
targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
}
}
//now do the files
var files = zReader.findEntries(filepath + "*");
while (files.hasMore()) {
var fname = files.getNext();
if (fname.substr(-1) != '/') {
var targetFile = buildRelativePath(fname, tmpdir, filepath);
zReader.extract(fname, targetFile);
}
}
return tmpdir;
}
/*
* Take a relative path from the current mochitest file
* and returns the absolute path for the given test data file.
*/
function getTestFilePath(path) {
if (path[0] == "/") {
throw new Error("getTestFilePath only accepts relative path");
}
// Get the chrome/jar uri for the current mochitest file
// gTestPath being defined by the test harness in browser-chrome tests
// or window is being used for mochitest-browser
var baseURI = typeof(gTestPath) == "string" ? gTestPath : window.location.href;
var parentURI = getResolvedURI(getRootDirectory(baseURI));
var file;
if (parentURI.JARFile) {
// If it's a jar/zip, we have to extract it first
file = extractJarToTmp(parentURI);
} else {
// Otherwise, we can directly cast it to a file URI
var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
getService(Components.interfaces.nsIFileProtocolHandler);
file = fileHandler.getFileFromURLSpec(parentURI.spec);
}
// Then walk by the given relative path
path.split("/")
.forEach(function (p) {
if (p == "..") {
file = file.parent;
} else if (p != ".") {
file.append(p);
}
});
return file.path;
}
/*
* Simple utility function to take the directory structure in jarentryname and
* translate that to a path of a nsILocalFile.
*/
function buildRelativePath(jarentryname, destdir, basepath)
{
var baseParts = basepath.split('/');
if (baseParts[baseParts.length-1] == '') {
baseParts.pop();
}
var parts = jarentryname.split('/');
var targetFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
targetFile.initWithFile(destdir);
for (var i = baseParts.length; i < parts.length; i++) {
targetFile.append(parts[i]);
}
return targetFile;
}
function readConfig(filename) {
filename = filename || "testConfig.js";
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties);
var configFile = fileLocator.get("ProfD", Components.interfaces.nsIFile);
configFile.append(filename);
if (!configFile.exists())
return {};
var fileInStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
fileInStream.init(configFile, -1, 0, 0);
var str = NetUtil.readInputStreamToString(fileInStream, fileInStream.available());
fileInStream.close();
return JSON.parse(str);
}
function registerTests() {
var testsURI = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("ProfD", Components.interfaces.nsILocalFile);
testsURI.append("tests.manifest");
var ioSvc = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var manifestFile = ioSvc.newFileURI(testsURI).
QueryInterface(Components.interfaces.nsIFileURL).file;
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).
autoRegister(manifestFile);
}
function getTestList(params, callback) {
registerTests();
var baseurl = 'chrome://mochitests/content';
if (window.parseQueryString) {
params = parseQueryString(location.search.substring(1), true);
}
if (!params.baseurl) {
params.baseurl = baseurl;
}
var config = readConfig();
for (var p in params) {
if (params[p] == 1) {
config[p] = true;
} else if (params[p] == 0) {
config[p] = false;
} else {
config[p] = params[p];
}
}
params = config;
if (params.manifestFile) {
getTestManifest("http://mochi.test:8888/" + params.manifestFile, params, callback);
return;
}
var links = {};
// load server.js in so we can share template functions
var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
var srvScope = {};
scriptLoader.loadSubScript('chrome://mochikit/content/server.js',
srvScope);
if (getResolvedURI(baseurl).JARFile) {
links = getMochitestJarListing(baseurl, params.testPath, params.testRoot);
} else {
links = getFileListing(baseurl, params.testPath, params.testRoot, srvScope);
}
callback(links);
}