Bug 1272851 - Allow temporary directory to be specified to xpcshell test harness; r=ted
authorGregory Szorc <gps@mozilla.com>
Thu, 26 May 2016 12:09:46 -0700
changeset 301193 4e80e15a246238e1b7447ab4f5df1010564e957c
parent 301192 e912f451cae4bb0383fbbc9811a931bac8166950
child 301194 4cbcf4d53eb8ec47d207366e7340366e1a69e6df
push id78244
push usergszorc@mozilla.com
push dateThu, 09 Jun 2016 00:37:28 +0000
treeherdermozilla-inbound@4cbcf4d53eb8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1272851
milestone50.0a1
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 1272851 - Allow temporary directory to be specified to xpcshell test harness; r=ted A subsequent commit will change where the temporary directory is located in certain test invocations. To do this, we need to teach the xpcshell harness to use an alternate temporary directory instead of using the system default (likely specified from TEMP* environment variables). MozReview-Commit-ID: IUUlYaLBiEC
testing/xpcshell/runxpcshelltests.py
testing/xpcshell/xpcshellcommandline.py
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -12,16 +12,17 @@ import mozdebug
 import mozinfo
 import os
 import os.path
 import random
 import re
 import shutil
 import signal
 import sys
+import tempfile
 import time
 import traceback
 
 from collections import deque, namedtuple
 from distutils import dir_util
 from multiprocessing import cpu_count
 from argparse import ArgumentParser
 from subprocess import Popen, PIPE, STDOUT
@@ -127,16 +128,17 @@ class XPCShellTestThread(Thread):
         self.singleFile = kwargs.get('singleFile')
         self.env = copy.deepcopy(kwargs.get('env'))
         self.symbolsPath = kwargs.get('symbolsPath')
         self.logfiles = kwargs.get('logfiles')
         self.xpcshell = kwargs.get('xpcshell')
         self.xpcsRunArgs = kwargs.get('xpcsRunArgs')
         self.failureManifest = kwargs.get('failureManifest')
         self.stack_fixer_function = kwargs.get('stack_fixer_function')
+        self._rootTempDir = kwargs.get('tempDir')
 
         self.app_dir_key = app_dir_key
         self.interactive = interactive
         self.verbose = verbose
         self.pStdout = pStdout
         self.pStderr = pStderr
         self.keep_going = keep_going
         self.log = log
@@ -316,27 +318,27 @@ class XPCShellTestThread(Thread):
         """
           Build the command line arguments for the test file.
           On a remote system, this may be overloaded to use a remote path structure.
         """
         return ['-e', 'const _TEST_FILE = ["%s"];' %
                   name.replace('\\', '/')]
 
     def setupTempDir(self):
-        tempDir = mkdtemp(prefix='xpc-other-')
+        tempDir = mkdtemp(prefix='xpc-other-', dir=self._rootTempDir)
         self.env["XPCSHELL_TEST_TEMP_DIR"] = tempDir
         if self.interactive:
             self.log.info("temp dir is %s" % tempDir)
         return tempDir
 
     def setupPluginsDir(self):
         if not os.path.isdir(self.pluginsPath):
             return None
 
-        pluginsDir = mkdtemp(prefix='xpc-plugins-')
+        pluginsDir = mkdtemp(prefix='xpc-plugins-', dir=self._rootTempDir)
         # shutil.copytree requires dst to not exist. Deleting the tempdir
         # would make a race condition possible in a concurrent environment,
         # so we are using dir_utils.copy_tree which accepts an existing dst
         dir_util.copy_tree(self.pluginsPath, pluginsDir)
         if self.interactive:
             self.log.info("plugins dir is %s" % pluginsDir)
         return pluginsDir
 
@@ -352,17 +354,17 @@ class XPCShellTestThread(Thread):
             profileDir = os.path.join(gettempdir(), self.profileName, "xpcshellprofile")
             try:
                 # This could be left over from previous runs
                 self.removeDir(profileDir)
             except:
                 pass
             os.makedirs(profileDir)
         else:
-            profileDir = mkdtemp(prefix='xpc-profile-')
+            profileDir = mkdtemp(prefix='xpc-profile-', dir=self._rootTempDir)
         self.env["XPCSHELL_TEST_PROFILE_DIR"] = profileDir
         if self.interactive or self.singleFile:
             self.log.info("profile dir is %s" % profileDir)
         return profileDir
 
     def setupMozinfoJS(self):
         mozInfoJSPath = os.path.join(self.profileDir, 'mozinfo.json')
         mozInfoJSPath = mozInfoJSPath.replace('\\', '\\\\')
@@ -1065,17 +1067,17 @@ class XPCShellTests(object):
 
         relpath_key = 'file_relpath' if 'file_relpath' in test_object else 'relpath'
         path = test_object[relpath_key].replace('\\', '/');
         if 'dupe-manifest' in test_object and 'ancestor-manifest' in test_object:
             return '%s:%s' % (os.path.basename(test_object['ancestor-manifest']), path)
         return path
 
     def runTests(self, xpcshell=None, xrePath=None, appPath=None, symbolsPath=None,
-                 manifest=None, testPaths=None, mobileArgs=None,
+                 manifest=None, testPaths=None, mobileArgs=None, tempDir=None,
                  interactive=False, verbose=False, keepGoing=False, logfiles=True,
                  thisChunk=1, totalChunks=1, debugger=None,
                  debuggerArgs=None, debuggerInteractive=False,
                  profileName=None, mozInfo=None, sequential=False, shuffle=False,
                  testingModulesDir=None, pluginsPath=None,
                  testClass=XPCShellTestThread, failureManifest=None,
                  log=None, stream=None, jsDebugger=False, jsDebuggerPort=0,
                  test_tags=None, dump_tests=None, utility_path=None,
@@ -1105,16 +1107,17 @@ class XPCShellTests(object):
         |debuggerInteractive|, if set, allows the debugger to be run in interactive
           mode.
         |profileName|, if set, specifies the name of the application for the profile
           directory if running only a subset of tests.
         |mozInfo|, if set, specifies specifies build configuration information, either as a filename containing JSON, or a dict.
         |shuffle|, if True, execute tests in random order.
         |testingModulesDir|, if provided, specifies where JS modules reside.
           xpcshell will register a resource handler mapping this path.
+        |tempDir|, if provided, specifies a temporary directory to use.
         |otherOptions| may be present for the convenience of subclasses
         """
 
         global gotSIGINT
 
         # Try to guess modules directory.
         # This somewhat grotesque hack allows the buildbot machines to find the
         # modules directory without having to configure the buildbot hosts. This
@@ -1158,16 +1161,17 @@ class XPCShellTests(object):
             # A namedtuple let's us keep .port instead of ['port']
             JSDebuggerInfo = namedtuple('JSDebuggerInfo', ['port'])
             self.jsDebuggerInfo = JSDebuggerInfo(port=jsDebuggerPort)
 
         self.xpcshell = xpcshell
         self.xrePath = xrePath
         self.appPath = appPath
         self.symbolsPath = symbolsPath
+        self.tempDir = os.path.normpath(tempDir or tempfile.gettempdir())
         self.manifest = manifest
         self.dump_tests = dump_tests
         self.interactive = interactive
         self.verbose = verbose
         self.keepGoing = keepGoing
         self.logfiles = logfiles
         self.totalChunks = totalChunks
         self.thisChunk = thisChunk
@@ -1244,16 +1248,17 @@ class XPCShellTests(object):
             'xrePath': self.xrePath,
             'testingModulesDir': self.testingModulesDir,
             'debuggerInfo': self.debuggerInfo,
             'jsDebuggerInfo': self.jsDebuggerInfo,
             'pluginsPath': self.pluginsPath,
             'httpdManifest': self.httpdManifest,
             'httpdJSPath': self.httpdJSPath,
             'headJSPath': self.headJSPath,
+            'tempDir': self.tempDir,
             'testharnessdir': self.testharnessdir,
             'profileName': self.profileName,
             'singleFile': self.singleFile,
             'env': self.env, # making a copy of this in the testthreads
             'symbolsPath': self.symbolsPath,
             'logfiles': self.logfiles,
             'xpcshell': self.xpcshell,
             'xpcsRunArgs': self.xpcsRunArgs,
--- a/testing/xpcshell/xpcshellcommandline.py
+++ b/testing/xpcshell/xpcshellcommandline.py
@@ -24,16 +24,19 @@ def add_common_arguments(parser):
                         type=unicode, dest="manifest", default=None,
                         help="Manifest of test directories to use")
     parser.add_argument("--no-logfiles",
                         action="store_false", dest="logfiles",
                         help="don't create log files")
     parser.add_argument("--sequential",
                         action="store_true", dest="sequential", default=False,
                         help="Run all tests sequentially")
+    parser.add_argument("--temp-dir",
+                        dest="tempDir", default=None,
+                        help="Directory to use for temporary files")
     parser.add_argument("--testing-modules-dir",
                         dest="testingModulesDir", default=None,
                         help="Directory where testing modules are located.")
     parser.add_argument("--test-plugin-path",
                         type=str, dest="pluginsPath", default=None,
                         help="Path to the location of a plugins directory containing the test plugin or plugins required for tests. "
                         "By default xpcshell's dir svc provider returns gre/plugins. Use test-plugin-path to add a directory "
                         "to return for NS_APP_PLUGINS_DIR_LIST when queried.")