Bug 543800 Package chrome style tests into .jar file for Android testing r=ted a=NPOTB
authorJoel Maher <jmaher@mozilla.com>
Thu, 30 Sep 2010 16:50:24 -0700
changeset 54819 7e4f8cb08cbaa5b15016689775b832876b8e0073
parent 54818 0f998c9f8728dc9069edef4c52ca2ed84235b909
child 54820 5fb749171234630fc5219f34d3170546afabba91
push id16041
push userctalbert@mozilla.com
push dateThu, 30 Sep 2010 23:59:26 +0000
treeherdermozilla-central@5fb749171234 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, NPOTB
bugs543800
milestone2.0b7pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 543800 Package chrome style tests into .jar file for Android testing r=ted a=NPOTB
Makefile.in
build/macosx/universal/flight.mk
testing/mochitest/Makefile.in
testing/mochitest/browser-harness.xul
testing/mochitest/chrome-harness.js
testing/mochitest/harness-overlay.xul
testing/mochitest/install.rdf
testing/mochitest/jar.mn
testing/mochitest/runtests.py.in
testing/mochitest/tests/SimpleTest/Makefile.in
testing/testsuite-targets.mk
--- a/Makefile.in
+++ b/Makefile.in
@@ -115,19 +115,16 @@ config.status: $(topsrcdir)/configure
 export::
 	$(RM) -rf $(DIST)/sdk
 	$(MAKE) -C config export
 	$(MAKE) tier_nspr
 
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
-else
-# OS X Universal builds will want to call this, so stub it out
-package-tests:
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 distclean::
 	cat unallmakefiles | $(XARGS) rm -f
 	rm -f unallmakefiles $(DIST_GARBAGE)
 
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -116,18 +116,18 @@ postflight_all:
           --unify-with-sort "\.manifest$$" \
           --unify-with-sort "components\.list$$" \
 	  $(DIST_ARCH_1)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
 	  $(DIST_ARCH_2)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
 	  $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
 # A universal .dmg can now be produced by making in either architecture's
 # INSTALLER_DIR.
 # Now, repeat the process for the test package.
-	$(MAKE) -C $(OBJDIR_ARCH_1) UNIVERSAL_BINARY= package-tests
-	$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= package-tests
+	$(MAKE) -C $(OBJDIR_ARCH_1) UNIVERSAL_BINARY= CHROME_JAR= package-tests
+	$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= CHROME_JAR= package-tests
 	rm -rf $(DIST_UNI)/test-package-stage
 # automation.py differs because it hardcodes a path to
 # dist/bin. It doesn't matter which one we use.
 	if test -d $(DIST_ARCH_1)/test-package-stage -a                 \
                 -d $(DIST_ARCH_2)/test-package-stage; then              \
            cp $(DIST_ARCH_1)/test-package-stage/mochitest/automation.py \
              $(DIST_ARCH_2)/test-package-stage/mochitest/;              \
            cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py   \
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -46,16 +46,29 @@ include $(DEPTH)/config/autoconf.mk
 DIRS =	MochiKit \
 	static \
 	dynamic \
 	tests \
 	chrome \
 	ssltunnel \
 	$(NULL)
 
+
+NO_JS_MANIFEST = 1
+MOZ_CHROME_FILE_FORMAT = jar
+DIST_FILES = install.rdf
+
+# Used in install.rdf
+USE_EXTENSION_MANIFEST = 1
+
+XPI_NAME = mochijar
+
+# we turn this off for UNIVERSAL_BINARY
+CHROME_JAR = 1
+
 include $(topsrcdir)/config/rules.mk
 # We're installing to _tests/testing/mochitest, so this is the depth
 # necessary for relative objdir paths.
 TARGET_DEPTH = ../../..
 include $(topsrcdir)/build/automation-build.mk
 
 # files that get copied into $objdir/_tests/
 _SERV_FILES = 	\
@@ -103,16 +116,19 @@ include $(topsrcdir)/build/automation-bu
 		pywebsocket/mod_pywebsocket/handshake/__init__.py \
 		pywebsocket/mod_pywebsocket/handshake/_base.py \
 		pywebsocket/mod_pywebsocket/handshake/draft75.py \
 		pywebsocket/mod_pywebsocket/handshake/handshake.py \
 		$(NULL)
 
 _DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir)
 
+libs:: 
+	(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - mochijar) | (cd $(_DEST_DIR) && tar -xf -)
+
 libs:: $(_PYWEBSOCKET_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(_DEST_DIR)/pywebsocket
 
 libs:: $(_MOD_PYWEBSOCKET_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(_DEST_DIR)/pywebsocket/mod_pywebsocket
 
 libs:: $(_HANDSHAKE_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(_DEST_DIR)/pywebsocket/mod_pywebsocket/handshake
@@ -170,16 +186,35 @@ else
 TEST_HARNESS_PLUGINS := \
   $(DLL_PREFIX)nptest$(DLL_SUFFIX)
 endif
 
 # Rules for staging the necessary harness bits for a test package
 PKG_STAGE = $(DIST)/test-package-stage
 DIST_BIN = $(DIST)/bin
 
+PKG_CHROMEJAR = $(PKG_STAGE)/mochitest/content/
+
+ifdef CHROME_JAR
+stage-chromejar:
+	$(NSINSTALL) -D $(PKG_CHROMEJAR)
+	cp -RL $(DEPTH)/_tests/testing/mochitest/browser $(PKG_CHROMEJAR)
+	cp -RL $(DEPTH)/_tests/testing/mochitest/chrome $(PKG_CHROMEJAR)
+ifdef ACCESSIBILITY
+	cp -RL $(DEPTH)/_tests/testing/mochitest/a11y $(PKG_CHROMEJAR)
+endif
+	@(cd $(PKG_STAGE)/mochitest && zip -r tests.jar content/)
+	@(rm -rf $(PKG_CHROMEJAR))
+
+stage-package: stage-chromejar
+endif
+
+$(_DEST_DIR):
+	$(NSINSTALL) -D $@
+
 stage-package:
 	$(NSINSTALL) -D $(PKG_STAGE)/mochitest && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins
 	@(cd $(DEPTH)/_tests/testing/mochitest/ && tar $(TAR_CREATE_FLAGS) - *) | (cd $(PKG_STAGE)/mochitest && tar -xf -)
 	@(cd $(DIST_BIN) && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_BINS)) | (cd $(PKG_STAGE)/bin && tar -xf -)
 	@(cd $(DIST_BIN)/components && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_COMPONENTS)) | (cd $(PKG_STAGE)/bin/components && tar -xf -)
 	@(cd $(topsrcdir)/build/pgo/certs && tar $(TAR_CREATE_FLAGS) - *) | (cd $(PKG_STAGE)/certs && tar -xf -)
 ifdef MOZ_PLUGINS
 	@(cd $(DIST_BIN)/plugins && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_PLUGINS)) | (cd $(PKG_STAGE)/bin/plugins && tar -xf -)
--- a/testing/mochitest/browser-harness.xul
+++ b/testing/mochitest/browser-harness.xul
@@ -203,25 +203,41 @@
           return "<p class=\"" + class + "\">" + t.result + " | " + path +
                  " | " + _entityEncode(t.msg) + "</p>";
         }).join("\n");
       }
     };
 
     // Returns an array of browserTest objects for all the selected tests
     function listTests() {
+      var baseURL = 'chrome://mochitests/content';
+      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);
 
       // load server.js in so we can share template functions
       var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
                          getService(Ci.mozIJSSubScriptLoader);
       var srvScope = {};
-      var baseURL = 'chrome://mochikit/content';
       scriptLoader.loadSubScript('chrome://mochikit/content/server.js', srvScope);
 
-      var [links, singleTestPath] = getFileListing(baseURL, gConfig.testPath, "browser", srvScope);
+      var jar = getJar(baseURL);
+      if (jar != null) {
+        var [links, singleTestPath] = getMochitestJarListing(baseURL, gConfig.testPath, "browser");
+      } else {
+        var [links, singleTestPath] = getFileListing(baseURL, gConfig.testPath, "browser", srvScope);
+      }
 
       var fileNames = [];
       var fileNameRegexp = /browser_.+\.js$/;
       srvScope.arrayOfTestFiles(links, fileNames, fileNameRegexp);
       return fileNames.map(function (f) new browserTest(f));
     }
 
     function setStatus(aStatusString) {
--- a/testing/mochitest/chrome-harness.js
+++ b/testing/mochitest/chrome-harness.js
@@ -103,52 +103,55 @@ function getMochitestJarListing(basePath
   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(basePath).JARFile.spec);
   zReader.open(fileName);
   //hardcoded 'content' as that is the root dir in the mochikit.jar file
+  var idx = basePath.indexOf('/content');
+  var basePath = basePath.slice(0, idx);
+
   var base = "content/" + dir + "/";
 
   var singleTestPath;
   if (testPath) {
     var extraPath = testPath;
     var pathToCheck = base + testPath;
     if (zReader.hasEntry(pathToCheck)) {
       var pathEntry = zReader.getEntry(pathToCheck);
       if (pathEntry.isDirectory) {
         base = pathToCheck;
       } else {
-        singleTestPath = '/' + base + testPath;
+        singleTestPath = basePath + '/' + base + testPath;
         var singleObject = {};
         singleObject[singleTestPath] = true;
         return [singleObject, singleTestPath];
       }
     }
     else if (zReader.hasEntry(pathToCheck + "/")) {
       base = pathToCheck + "/";
     }
   }
-  var [links, count] = zList(base, zReader, true);
+  var [links, count] = zList(base, zReader, basePath, true);
   return [links, null];
 }
 
 /*
  * 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, recurse) {
+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) ||
@@ -157,22 +160,22 @@ function zList(base, zReader, recurse) {
     }
   }
   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, recurse);
+      [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['/' + myFile] = true;
+        links[baseJarName + '/' + myFile] = true;
       }
     }
   }
   return [links, count];
 }
 
 /**
  * basePath: the URL base path to search from such as chrome://mochikit/content/a11y
@@ -278,17 +281,17 @@ function getJar(uri) {
  */
 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));
+  tmpdir.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
 
   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);
@@ -306,17 +309,17 @@ function extractJarToTmp(jar) {
   /* 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)
-    targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
+    targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
   }
 
   //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);
--- a/testing/mochitest/harness-overlay.xul
+++ b/testing/mochitest/harness-overlay.xul
@@ -12,86 +12,69 @@
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/MozillaFileLogger.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/quit.js" />
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/setup.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/chrome-harness.js" />
   <script type="application/javascript;version=1.7"><![CDATA[
-    function loadTests()
-    {
-      window.removeEventListener("load", loadTests, false);
+
+function loadTests()
+{
+  window.removeEventListener("load", loadTests, false);
 
-      var dir = document.documentElement.getAttribute('directory');
-      var url = "chrome://mochikit/content/" + dir + "/";
-      // Find our chrome dir
-      var ios = Cc["@mozilla.org/network/io-service;1"].
-                  getService(Ci.nsIIOService);
-      var chromeURI = ios.newURI("chrome://mochikit/content/",
-                                 null, null);
-      var resolvedURI = Cc["@mozilla.org/chrome/chrome-registry;1"].
-                          getService(Ci.nsIChromeRegistry).
-                          convertChromeURL(chromeURI);
-      var fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
-                          getService(Ci.nsIFileProtocolHandler);
-      var chromeDir = fileHandler.getFileFromURLSpec(resolvedURI.spec);
-      chromeDir = chromeDir.parent.QueryInterface(Ci.nsILocalFile);
-      chromeDir.appendRelativePath(dir);
+  var baseurl = 'chrome://mochitests/content';
+  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);
+
+  var dir = document.documentElement.getAttribute('directory');
 
-      var singleTestPath;
-      if ("testPath" in params && params.testPath) {
-        var extraPath = params.testPath;
-        var pathToCheck = chromeDir.clone().QueryInterface(Ci.nsILocalFile);
-        var pathIsFile = false;
-        try {
-          var pathParts = extraPath.toString().split("/");
-          for each (var part in pathParts) {
-            pathToCheck.append(part);
-          }          
-          if (pathToCheck.isDirectory()) {
-            for each (var part in pathParts) {
-              chromeDir.append(part);
-            }          
-            url += extraPath + "/";
-          }
-          else {
-            pathIsFile = true;
-          }
-        }
-        catch (e) {
-          pathIsFile = true;
-        }
-        if (pathIsFile) {
-          singleTestPath = url + params.testPath;
-        }
-      }
-      // 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);
+  // 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);
+  // generate our test list
+  srvScope.makeTags();
+
+  var singleTestPath;
+  var links;
 
-      // generate our test list
-      srvScope.makeTags();
-      var [links, count] = srvScope.list(url, chromeDir, true);
-      var tableContent = srvScope.linksToTableRows(links, 0);
-      function populate() {
-        $("test-table").innerHTML += tableContent;
-      }
-      gTestList = eval(srvScope.jsonArrayOfTestFiles(links));
-      populate();
-      hookup();
+  if (getResolvedURI(baseurl).JARFile) {
+    [links, singleTestPath] = getMochitestJarListing(baseurl, params.testPath, dir);
+  } else {
+    [links, singleTestPath] = getFileListing(baseurl, params.testPath, dir, srvScope);
+  }
+  
+  var tableContent = srvScope.linksToTableRows(links, 0);
 
-      // if we got passed a test path, just run that single test
-      if (singleTestPath)
-        window.location.href = singleTestPath;
-    }
+  function populate() {
+    $("test-table").innerHTML += tableContent;
+  }
+  gTestList = eval(srvScope.jsonArrayOfTestFiles(links));
+  populate();
+  hookup();
+
+  if (singleTestPath)
+    window.location.href = singleTestPath;
+}
 
     window.addEventListener("load", loadTests, false);
   ]]>
   </script>
 
   <vbox>   
     <button label="Run Chrome Tests" id="runtests" flex="1"/>
 
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/install.rdf
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>mochikit@mozilla.org</em:id>
+    <em:version>1.0</em:version>
+    <em:targetApplication>
+      <Description>
+        <em:id>toolkit@mozilla.org</em:id>
+#expand        <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
+#expand        <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+    <!-- Front End MetaData -->
+    <em:name>Mochitest</em:name>
+    <em:description>Mochikit test harness</em:description>
+    <em:creator>Joel Maher</em:creator>
+  </Description>
+</RDF>
+
+
+
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/jar.mn
@@ -0,0 +1,39 @@
+mochikit.jar:
+% content mochikit %content/
+  content/browser-harness.xul (browser-harness.xul)
+  content/browser-test.js (browser-test.js)
+  content/browser-test-overlay.xul (browser-test-overlay.xul)
+  content/chrome-harness.js (chrome-harness.js)
+  content/harness-a11y.xul (harness-a11y.xul)
+  content/harness-overlay.xul (harness-overlay.xul)
+  content/harness.xul (harness.xul)
+  content/ipc.js (ipc.js)
+  content/ipc-overlay.xul (ipc-overlay.xul)
+  content/mozprefs.js (mozprefs.js)
+  content/redirect-a11y.html (redirect-a11y.html)
+  content/redirect.html (redirect.html)
+  content/redirect.js (redirect.js)
+  content/server.js (server.js)
+  content/dynamic/getMyDirectory.sjs (dynamic/getMyDirectory.sjs)
+  content/static/bug100533_iframe.html (static/bug100533_iframe.html)
+  content/static/bug100533_load.html (static/bug100533_load.html)
+  content/static/bug277724_iframe1.html (static/bug277724_iframe1.html)
+  content/static/bug277724_iframe2.xhtml (static/bug277724_iframe2.xhtml)
+  content/static/bug340800_iframe.txt (static/bug340800_iframe.txt)
+  content/static/bug344830_testembed.svg (static/bug344830_testembed.svg)
+  content/static/harness.css (static/harness.css)
+  content/static/nnc_lockup.gif (static/nnc_lockup.gif)
+  content/tests/SimpleTest/EventUtils.js (tests/SimpleTest/EventUtils.js)
+  content/tests/SimpleTest/MozillaFileLogger.js (tests/SimpleTest/MozillaFileLogger.js)
+  content/tests/SimpleTest/PluginUtils.js (tests/SimpleTest/PluginUtils.js)
+  content/tests/SimpleTest/quit.js (tests/SimpleTest/quit.js)
+  content/tests/SimpleTest/setup.js (tests/SimpleTest/setup.js)
+  content/tests/SimpleTest/SimpleTest.js (tests/SimpleTest/SimpleTest.js)
+  content/tests/SimpleTest/test.css (tests/SimpleTest/test.css)
+  content/tests/SimpleTest/TestRunner.js (tests/SimpleTest/TestRunner.js)
+  content/tests/SimpleTest/WindowSnapshot.js (tests/SimpleTest/WindowSnapshot.js)
+  content/tests/SimpleTest/mockObjects.js (../../toolkit/content/tests/browser/common/mockObjects.js)
+  content/tests/SimpleTest/docshell_helpers.js (../..//docshell/test/chrome/docshell_helpers.js)
+
+  content/MochiKit/packed.js (MochiKit/packed.js)
+
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -37,16 +37,17 @@
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 """
 Runs the Mochitest test harness.
 """
 
+from __future__ import with_statement
 from datetime import datetime
 import optparse
 import os
 import os.path
 import sys
 import time
 import shutil
 from urllib import quote_plus as encodeURIComponent
@@ -338,17 +339,17 @@ class MochitestServer:
 
   def stop(self):
     try:
       c = urllib2.urlopen(self.shutdownURL)
       c.read()
       c.close()
 
       rtncode = self._process.poll()
-      if (rtncode == None):
+      if rtncode is None:
         self._process.terminate()
     except:
       self._process.kill()
 
 class WebSocketServer(object):
   "Class which encapsulates the mod_pywebsocket server"
 
   def __init__(self, automation, options, scriptdir):
@@ -563,26 +564,28 @@ class Mochitest(object):
   def runTests(self, options):
     """ Prepare, configure, run tests and cleanup """
     debuggerInfo = getDebuggerInfo(self.oldcwd, options.debugger, options.debuggerArgs,
                       options.debuggerInteractive);
 
     self.leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log")
 
     browserEnv = self.buildBrowserEnv(options)
-    if (browserEnv == None):
+    if browserEnv is None:
       return 1
 
     manifest = self.buildProfile(options)
+    if manifest is None:
+      return 1
     self.startWebServer(options)
     self.startWebSocketServer(options)
 
     testURL = self.buildTestPath(options)
     self.buildURLOptions(options)
-    if (len(self.urlOpts) > 0):
+    if len(self.urlOpts) > 0:
       testURL += "?" + "&".join(self.urlOpts)
 
     # Remove the leak detection file so it can't "leak" to the tests run.
     # The file is not there if leak logging was not enabled in the application build.
     if os.path.exists(self.leak_report_file):
       os.remove(self.leak_report_file)
 
     # then again to actually run mochitest
@@ -610,17 +613,18 @@ class Mochitest(object):
     if options.vmwareRecording:
       self.stopVMwareRecording();
 
     self.stopWebServer(options)
     self.stopWebSocketServer(options)
     processLeakLog(self.leak_report_file, options.leakThreshold)
     self.automation.log.info("\nINFO | runtests.py | Running tests: end.")
 
-    self.cleanup(manifest, options)
+    if manifest is not None:
+      self.cleanup(manifest, options)
     return status
 
   def makeTestConfig(self, options):
     "Creates a test configuration file for customizing test execution."
     def boolString(b):
       if b:
         return "true"
       return "false"
@@ -668,37 +672,63 @@ toolbar#nav-bar {
 
     # register our chrome dir
     chrometestDir = os.path.abspath(".") + "/"
     if self.automation.IS_WIN32:
       chrometestDir = "file:///" + chrometestDir.replace("\\", "/")
 
     temp_file = os.path.join(tempfile.mkdtemp(), "mochikit.manifest")
     manifestFile = open(temp_file, "w")
-    manifestFile.write("content mochikit " + chrometestDir + " contentaccessible=yes\n")
 
+    browser_chrome = ""
     if options.browserChrome:
-      manifestFile.write("""overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
+      browser_chrome = """overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
 overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
-""")
-    elif ((options.chrome == False) and (options.a11y == False)):
+"""
+    elif (options.chrome == False) and (options.a11y == False):
       #only do the ipc-overlay.xul for mochitest-plain.  
       #Currently there are focus issues in chrome tests and issues with new windows and dialogs when using ipc
-      manifestFile.write("overlay chrome://browser/content/browser.xul chrome://mochikit/content/ipc-overlay.xul")
+      browser_chrome += "overlay chrome://browser/content/browser.xul chrome://mochikit/content/ipc-overlay.xul\n"
+
+    jarDir = 'mochijar'
+    if not os.path.exists(os.path.join(self.SCRIPT_DIRECTORY, jarDir)):
+      print "TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension"
+      return None
+
+    if self.installTestsJar(options):
+      manifestFile.write("content mochitests jar:tests.jar!/content/\n");
+    else:
+      manifestFile.write("content mochitests %s contentaccessible=yes\n" % chrometestDir)
+    self.installChromeJar(jarDir, browser_chrome, options)
       
     manifestFile.close()
 
     return self.installChromeFile(temp_file, options)
 
+  def installChromeJar(self, jarDirName, browser_chrome, options):
+    """
+      copy mochijar directory to profile as an extension so we have chrome://mochikit for all harness code
+    """
+    jarDir = os.path.join(options.profilePath, 'extensions', 'mochikit@mozilla.org')
+    shutil.copytree(os.path.join(self.SCRIPT_DIRECTORY, jarDirName), jarDir)
+    with open(os.path.join(jarDir, "chrome.manifest"), 'a') as mfile:
+      mfile.write(browser_chrome)
+
+    return jarDir
+
+  def installTestsJar(self, options):
+    """ copy tests.jar to the profile directory so we can auto register it in the .xul harness """
+    if os.path.exists(os.path.join(self.SCRIPT_DIRECTORY, 'tests.jar')):
+      shutil.copy(os.path.join(self.SCRIPT_DIRECTORY, 'tests.jar'), options.profilePath)
+      return True
+    return False
+
   def installChromeFile(self, filename, options):
-    (path, leaf) = os.path.split(options.app)
-    manifestdir = os.path.join(path, "distribution", "bundles", "mochitest")
-    if not os.path.exists(manifestdir):
-      os.makedirs(manifestdir)
-    manifest = os.path.join(manifestdir, "chrome.manifest")
+    """ copy tests.manifest to the profile directory so we can auto register with tests.jar """
+    manifest = os.path.join(options.profilePath, 'tests.manifest')
     shutil.copy(filename, manifest)
     return manifest
 
   def copyExtraFilesToProfile(self, options):
     "Copy extra files or dirs specified on the command line to the testing profile."
     for f in options.extraProfileFiles:
       abspath = self.getFullPath(f)
       dest = os.path.join(options.profilePath, os.path.basename(abspath))
--- a/testing/mochitest/tests/SimpleTest/Makefile.in
+++ b/testing/mochitest/tests/SimpleTest/Makefile.in
@@ -50,13 +50,14 @@ include $(topsrcdir)/config/rules.mk
 			SimpleTest.js \
 			test.css \
 			TestRunner.js \
 			setup.js \
 			EventUtils.js \
 			WindowSnapshot.js \
 			PluginUtils.js \
 			$(DEPTH)/toolkit/content/tests/browser/common/mockObjects.js \
+                        $(DEPTH)/docshell/test/chrome/docshell_helpers.js \
 			$(NULL)
 
 libs:: $(_SIMPLETEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/$(relativesrcdir)
 
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -137,18 +137,23 @@ ifndef UNIVERSAL_BINARY
 PKG_STAGE = $(DIST)/test-package-stage
 package-tests: stage-mochitest stage-reftest stage-xpcshell stage-jstests stage-mozmill stage-jetpack
 else
 # This staging area has been built for us by universal/flight.mk
 PKG_STAGE = $(DIST)/universal/test-package-stage
 endif
 
 package-tests:
+	@rm -f "$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)"
+ifndef UNIVERSAL_BINARY
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
-	@rm -f "$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)"
+else
+	#building tests.jar (bug 543800) fails on unify, so we build tests.jar after unify is run
+	$(MAKE) -C $(DEPTH)/testing/mochitest stage-chromejar PKG_STAGE=$(DIST)/universal
+endif
 	cd $(PKG_STAGE) && \
 	  zip -r9D "$(call core_abspath,$(DIST)/$(PKG_PATH)$(TEST_PACKAGE))" *
 
 ifeq (Android, $(OS_TARGET))
 package-tests: stage-android
 endif
 
 make-stage-dir: