Bug 822875 - Make TPS .py files use 4-space indent, r=jgriffin
authorVignesh Sarma <vignesh.sarma@gmail.com>
Fri, 11 Jan 2013 13:32:50 -0800
changeset 128407 4ffaf917d5c0bdf3890bb60c0a3ca7a50b03c333
parent 128406 1e80bc5cbeba5c8dde9c689f654b50260f8d5f50
child 128408 f2c240863a0ca23e06662c5bba128e1a530039d1
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgriffin
bugs822875
milestone21.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 822875 - Make TPS .py files use 4-space indent, r=jgriffin
testing/tps/tps/cli.py
testing/tps/tps/firefoxrunner.py
testing/tps/tps/mozhttpd.py
testing/tps/tps/phase.py
testing/tps/tps/testrunner.py
testing/tps/tps/thread.py
--- a/testing/tps/tps/cli.py
+++ b/testing/tps/tps/cli.py
@@ -7,93 +7,93 @@ import optparse
 import os
 import sys
 
 from threading import RLock
 
 from tps import TPSTestRunner
 
 def main():
-  parser = optparse.OptionParser()
-  parser.add_option("--mobile",
-                    action = "store_true", dest = "mobile",
-                    default = False,
-                    help = "run with mobile settings")
-  parser.add_option("--testfile",
-                    action = "store", type = "string", dest = "testfile",
-                    default = '../../services/sync/tests/tps/test_sync.js',
-                    help = "path to the test file to run "
-                           "[default: %default]")
-  parser.add_option("--logfile",
-                    action = "store", type = "string", dest = "logfile",
-                    default = 'tps.log',
-                    help = "path to the log file [default: %default]")
-  parser.add_option("--resultfile",
-                    action = "store", type = "string", dest = "resultfile",
-                    default = 'tps_result.json',
-                    help = "path to the result file [default: %default]")
-  parser.add_option("--binary",
-                    action = "store", type = "string", dest = "binary",
-                    default = None,
-                    help = "path to the Firefox binary, specified either as "
-                           "a local file or a url; if omitted, the PATH "
-                           "will be searched;")
-  parser.add_option("--configfile",
-                    action = "store", type = "string", dest = "configfile",
-                    default = None,
-                    help = "path to the config file to use "
-                           "[default: %default]")
-  parser.add_option("--pulsefile",
-                    action = "store", type = "string", dest = "pulsefile",
-                    default = None,
-                    help = "path to file containing a pulse message in "
-                           "json format that you want to inject into the monitor")
-  parser.add_option("--ignore-unused-engines",
-                     default=False,
-                     action="store_true",
-                     dest="ignore_unused_engines",
-                     help="If defined, don't load unused engines in individual tests."
-                           " Has no effect for pulse monitor.")
-  (options, args) = parser.parse_args()
+    parser = optparse.OptionParser()
+    parser.add_option("--mobile",
+                      action = "store_true", dest = "mobile",
+                      default = False,
+                      help = "run with mobile settings")
+    parser.add_option("--testfile",
+                      action = "store", type = "string", dest = "testfile",
+                      default = '../../services/sync/tests/tps/test_sync.js',
+                      help = "path to the test file to run "
+                             "[default: %default]")
+    parser.add_option("--logfile",
+                      action = "store", type = "string", dest = "logfile",
+                      default = 'tps.log',
+                      help = "path to the log file [default: %default]")
+    parser.add_option("--resultfile",
+                      action = "store", type = "string", dest = "resultfile",
+                      default = 'tps_result.json',
+                      help = "path to the result file [default: %default]")
+    parser.add_option("--binary",
+                      action = "store", type = "string", dest = "binary",
+                      default = None,
+                      help = "path to the Firefox binary, specified either as "
+                             "a local file or a url; if omitted, the PATH "
+                             "will be searched;")
+    parser.add_option("--configfile",
+                      action = "store", type = "string", dest = "configfile",
+                      default = None,
+                      help = "path to the config file to use "
+                             "[default: %default]")
+    parser.add_option("--pulsefile",
+                      action = "store", type = "string", dest = "pulsefile",
+                      default = None,
+                      help = "path to file containing a pulse message in "
+                             "json format that you want to inject into the monitor")
+    parser.add_option("--ignore-unused-engines",
+                       default=False,
+                       action="store_true",
+                       dest="ignore_unused_engines",
+                       help="If defined, don't load unused engines in individual tests."
+                             " Has no effect for pulse monitor.")
+    (options, args) = parser.parse_args()
 
-  configfile = options.configfile
-  if configfile is None:
-    if os.environ.get('VIRTUAL_ENV'):
-      configfile = os.path.join(os.path.dirname(__file__), 'config.json')
-    if configfile is None or not os.access(configfile, os.F_OK):
-      raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
-                      "specify a config file using the --configfile option")
+    configfile = options.configfile
+    if configfile is None:
+        if os.environ.get('VIRTUAL_ENV'):
+            configfile = os.path.join(os.path.dirname(__file__), 'config.json')
+        if configfile is None or not os.access(configfile, os.F_OK):
+            raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
+                            "specify a config file using the --configfile option")
 
-  # load the config file
-  f = open(configfile, 'r')
-  configcontent = f.read()
-  f.close()
-  config = json.loads(configcontent)
+    # load the config file
+    f = open(configfile, 'r')
+    configcontent = f.read()
+    f.close()
+    config = json.loads(configcontent)
 
-  rlock = RLock()
+    rlock = RLock()
 
-  print 'using result file', options.resultfile
+    print 'using result file', options.resultfile
 
-  extensionDir = config.get("extensiondir")
-  if not extensionDir or extensionDir == '__EXTENSIONDIR__':
-    extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps")
-  else:
-    if sys.platform == 'win32':
-      # replace msys-style paths with proper Windows paths
-      import re
-      m = re.match('^\/\w\/', extensionDir)
-      if m:
-        extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
-        extensionDir = extensionDir.replace("/", "\\")
+    extensionDir = config.get("extensiondir")
+    if not extensionDir or extensionDir == '__EXTENSIONDIR__':
+        extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps", "extensions")
+    else:
+        if sys.platform == 'win32':
+            # replace msys-style paths with proper Windows paths
+            import re
+            m = re.match('^\/\w\/', extensionDir)
+            if m:
+                extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
+                extensionDir = extensionDir.replace("/", "\\")
 
-  TPS = TPSTestRunner(extensionDir,
-                      testfile=options.testfile,
-                      logfile=options.logfile,
-                      binary=options.binary,
-                      config=config,
-                      rlock=rlock,
-                      mobile=options.mobile,
-                      resultfile=options.resultfile,
-                      ignore_unused_engines=options.ignore_unused_engines)
-  TPS.run_tests()
+    TPS = TPSTestRunner(extensionDir,
+                        testfile=options.testfile,
+                        logfile=options.logfile,
+                        binary=options.binary,
+                        config=config,
+                        rlock=rlock,
+                        mobile=options.mobile,
+                        resultfile=options.resultfile,
+                        ignore_unused_engines=options.ignore_unused_engines)
+    TPS.run_tests()
 
 if __name__ == "__main__":
-  main()
+    main()
--- a/testing/tps/tps/firefoxrunner.py
+++ b/testing/tps/tps/firefoxrunner.py
@@ -9,86 +9,86 @@ import shutil
 
 import mozinstall
 
 from mozprofile import Profile
 from mozrunner import FirefoxRunner
 
 class TPSFirefoxRunner(object):
 
-  PROCESS_TIMEOUT = 240
-
-  def __init__(self, binary):
-    if binary is not None and ('http://' in binary or 'ftp://' in binary):
-      self.url = binary
-      self.binary = None
-    else:
-      self.url = None
-      self.binary = binary
-    self.runner = None
-    self.installdir = None
-
-  def __del__(self):
-    if self.installdir:
-      shutil.rmtree(self.installdir, True)
-
-  def download_url(self, url, dest=None):
-    h = httplib2.Http()
-    resp, content = h.request(url, "GET")
-    if dest == None:
-        dest = os.path.basename(url)
-
-    local = open(dest, 'wb')
-    local.write(content)
-    local.close()
-    return dest
-
-  def download_build(self, installdir='downloadedbuild', appname='firefox'):
-    self.installdir = os.path.abspath(installdir)
-    buildName = os.path.basename(self.url)
-    pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                               buildName)
-
-    # delete the build if it already exists
-    if os.access(pathToBuild, os.F_OK):
-      os.remove(pathToBuild)
-
-    # download the build
-    print "downloading build"
-    self.download_url(self.url, pathToBuild)
-
-    # install the build
-    print "installing %s" % pathToBuild
-    shutil.rmtree(self.installdir, True)
-    binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
-
-    # remove the downloaded archive
-    os.remove(pathToBuild)
-
-    return binary
-
-  def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
-    """Runs the given FirefoxRunner with the given Profile, waits
-       for completion, then returns the process exit code
-    """
-    if profile is None:
-      profile = Profile()
-    self.profile = profile
-
-    if self.binary is None and self.url:
-      self.binary = self.download_build()
-
-    if self.runner is None:
-      self.runner = FirefoxRunner(self.profile, binary=self.binary)
-
-    self.runner.profile = self.profile
-
-    if env is not None:
-      self.runner.env.update(env)
-
-    if args is not None:
-      self.runner.cmdargs = copy.copy(args)
-
-    self.runner.start()
-
-    status = self.runner.process_handler.waitForFinish(timeout=timeout)
-
-    return status
+    PROCESS_TIMEOUT = 240
+  
+    def __init__(self, binary):
+        if binary is not None and ('http://' in binary or 'ftp://' in binary):
+            self.url = binary
+            self.binary = None
+        else:
+            self.url = None
+            self.binary = binary
+        self.runner = None
+        self.installdir = None
+    
+    def __del__(self):
+        if self.installdir:
+            shutil.rmtree(self.installdir, True)
+      
+    def download_url(self, url, dest=None):
+        h = httplib2.Http()
+        resp, content = h.request(url, "GET")
+        if dest == None:
+            dest = os.path.basename(url)
+    
+        local = open(dest, 'wb')
+        local.write(content)
+        local.close()
+        return dest
+    
+    def download_build(self, installdir='downloadedbuild', appname='firefox'):
+        self.installdir = os.path.abspath(installdir)
+        buildName = os.path.basename(self.url)
+        pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                                   buildName)
+    
+        # delete the build if it already exists
+        if os.access(pathToBuild, os.F_OK):
+            os.remove(pathToBuild)
+      
+        # download the build
+        print "downloading build"
+        self.download_url(self.url, pathToBuild)
+    
+        # install the build
+        print "installing %s" % pathToBuild
+        shutil.rmtree(self.installdir, True)
+        binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
+    
+        # remove the downloaded archive
+        os.remove(pathToBuild)
+    
+        return binary
+    
+    def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
+        """Runs the given FirefoxRunner with the given Profile, waits
+           for completion, then returns the process exit code
+        """
+        if profile is None:
+            profile = Profile()
+        self.profile = profile
+    
+        if self.binary is None and self.url:
+            self.binary = self.download_build()
+      
+        if self.runner is None:
+            self.runner = FirefoxRunner(self.profile, binary=self.binary)
+      
+        self.runner.profile = self.profile
+    
+        if env is not None:
+            self.runner.env.update(env)
+      
+        if args is not None:
+            self.runner.cmdargs = copy.copy(args)
+      
+        self.runner.start()
+    
+        status = self.runner.process_handler.waitForFinish(timeout=timeout)
+    
+        return status
--- a/testing/tps/tps/mozhttpd.py
+++ b/testing/tps/tps/mozhttpd.py
@@ -13,20 +13,20 @@ import urllib
 import re
 from urlparse import urlparse
 from SocketServer import ThreadingMixIn
 
 DOCROOT = '.'
 
 class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
     allow_reuse_address = True
-    
+
 class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
     def translate_path(self, path):
-        # It appears that the default path is '/' and os.path.join makes the '/' 
+        # It appears that the default path is '/' and os.path.join makes the '/'
         o = urlparse(path)
 
         sep = '/'
         if sys.platform == 'win32':
             sep = ''
 
         ret = '%s%s' % ( sep, DOCROOT.strip('/') )
 
@@ -87,19 +87,18 @@ class MozHttpd(object):
             webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@')
             if webline != "":
                 if webline == "Directory listing for":
                     found = True
                 else:
                     for fileName in fileList:
                         if fileName == webline:
                             found = True
-                
+
                 if (found == False):
-                    print "NOT FOUND: " + webline.strip()                
+                    print "NOT FOUND: " + webline.strip()
 
     def stop(self):
         if self.httpd:
             self.httpd.shutdown()
             self.httpd.server_close()
 
     __del__ = stop
-
--- a/testing/tps/tps/phase.py
+++ b/testing/tps/tps/phase.py
@@ -1,76 +1,75 @@
 # 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/.
 
 import re
 
 class TPSTestPhase(object):
 
-  lineRe = re.compile(
-      r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
+    lineRe = re.compile(
+        r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
 
-  def __init__(self, phase, profile, testname, testpath, logfile, env,
-               firefoxRunner, logfn, ignore_unused_engines=False):
-    self.phase = phase
-    self.profile = profile
-    self.testname = str(testname) # this might be passed in as unicode
-    self.testpath = testpath
-    self.logfile = logfile
-    self.env = env
-    self.firefoxRunner = firefoxRunner
-    self.log = logfn
-    self.ignore_unused_engines = ignore_unused_engines
-    self._status = None
-    self.errline = ''
+    def __init__(self, phase, profile, testname, testpath, logfile, env,
+                 firefoxRunner, logfn, ignore_unused_engines=False):
+        self.phase = phase
+        self.profile = profile
+        self.testname = str(testname) # this might be passed in as unicode
+        self.testpath = testpath
+        self.logfile = logfile
+        self.env = env
+        self.firefoxRunner = firefoxRunner
+        self.log = logfn
+        self.ignore_unused_engines = ignore_unused_engines
+        self._status = None
+        self.errline = ''
 
-  @property
-  def phasenum(self):
-    match = re.match('.*?(\d+)', self.phase)
-    if match:
-      return match.group(1)
+    @property
+    def phasenum(self):
+        match = re.match('.*?(\d+)', self.phase)
+        if match:
+            return match.group(1)
 
-  @property
-  def status(self):
-    return self._status if self._status else 'unknown'
+    @property
+    def status(self):
+        return self._status if self._status else 'unknown'
 
-  def run(self):
-    # launch Firefox
-    args = [ '-tps', self.testpath,
-             '-tpsphase', self.phasenum,
-             '-tpslogfile', self.logfile ]
+    def run(self):
+        # launch Firefox
+        args = [ '-tps', self.testpath,
+                 '-tpsphase', self.phasenum,
+                 '-tpslogfile', self.logfile ]
 
-    if self.ignore_unused_engines:
-        args.append('--ignore-unused-engines')
+        if self.ignore_unused_engines:
+            args.append('--ignore-unused-engines')
 
-    self.log("\nlaunching Firefox for phase %s with args %s\n" %
-             (self.phase, str(args)))
-    self.firefoxRunner.run(env=self.env,
-                           args=args,
-                           profile=self.profile)
+        self.log("\nlaunching Firefox for phase %s with args %s\n" %
+                 (self.phase, str(args)))
+        self.firefoxRunner.run(env=self.env,
+                               args=args,
+                               profile=self.profile)
 
-    # parse the logfile and look for results from the current test phase
-    found_test = False
-    f = open(self.logfile, 'r')
-    for line in f:
+        # parse the logfile and look for results from the current test phase
+        found_test = False
+        f = open(self.logfile, 'r')
+        for line in f:
 
-      # skip to the part of the log file that deals with the test we're running
-      if not found_test:
-        if line.find("Running test %s" % self.testname) > -1:
-          found_test = True
-        else:
-          continue
+            # skip to the part of the log file that deals with the test we're running
+            if not found_test:
+                if line.find("Running test %s" % self.testname) > -1:
+                    found_test = True
+                else:
+                    continue
 
-      # look for the status of the current phase
-      match = self.lineRe.match(line)
-      if match:
-        if match.group("matchphase") == self.phasenum:
-          self._status = match.group("matchstatus")
-          break
+            # look for the status of the current phase
+            match = self.lineRe.match(line)
+            if match:
+                if match.group("matchphase") == self.phasenum:
+                    self._status = match.group("matchstatus")
+                    break
 
-      # set the status to FAIL if there is TPS error
-      if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
-        self._status = "FAIL"
-        self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
+            # set the status to FAIL if there is TPS error
+            if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
+                self._status = "FAIL"
+                self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
 
-    f.close()
-
+        f.close()
--- a/testing/tps/tps/testrunner.py
+++ b/testing/tps/tps/testrunner.py
@@ -13,418 +13,418 @@ import traceback
 
 from mozprofile import Profile
 
 from tps.firefoxrunner import TPSFirefoxRunner
 from tps.phase import TPSTestPhase
 from tps.mozhttpd import MozHttpd
 
 class TempFile(object):
-  """Class for temporary files that delete themselves when garbage-collected.
-  """
+    """Class for temporary files that delete themselves when garbage-collected.
+    """
 
-  def __init__(self, prefix=None):
-    self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
+    def __init__(self, prefix=None):
+        self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
 
-  def write(self, data):
-    if self.fd:
-      os.write(self.fd, data)
+    def write(self, data):
+        if self.fd:
+            os.write(self.fd, data)
 
-  def close(self):
-    if self.fd:
-      os.close(self.fd)
-      self.fd = None
+    def close(self):
+        if self.fd:
+            os.close(self.fd)
+            self.fd = None
 
-  def cleanup(self):
-    if self.fd:
-      self.close()
-    if os.access(self.filename, os.F_OK):
-      os.remove(self.filename)
+    def cleanup(self):
+        if self.fd:
+            self.close()
+        if os.access(self.filename, os.F_OK):
+            os.remove(self.filename)
 
-  __del__ = cleanup
+    __del__ = cleanup
 
 class TPSTestRunner(object):
 
-  default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
-                  'GNOME_DISABLE_CRASH_DIALOG': '1',
-                  'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
-                  'MOZ_NO_REMOTE': '1',
-                  'XPCOM_DEBUG_BREAK': 'warn',
-                }
-  default_preferences = { 'app.update.enabled' : False,
-                          'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
-                          'extensions.update.enabled'    : False,
-                          'extensions.update.notifyUser' : False,
-                          'browser.shell.checkDefaultBrowser' : False,
-                          'browser.tabs.warnOnClose' : False,
-                          'browser.warnOnQuit': False,
-                          'browser.sessionstore.resume_from_crash': False,
-                          'services.sync.addons.ignoreRepositoryChecking': True,
-                          'services.sync.firstSync': 'notReady',
-                          'services.sync.lastversion': '1.0',
-                          'services.sync.log.rootLogger': 'Trace',
-                          'services.sync.log.logger.engine.addons': 'Trace',
-                          'services.sync.log.logger.service.main': 'Trace',
-                          'services.sync.log.logger.engine.bookmarks': 'Trace',
-                          'services.sync.log.appender.console': 'Trace',
-                          'services.sync.log.appender.debugLog.enabled': True,
-                          'toolkit.startup.max_resumed_crashes': -1,
-                          'browser.dom.window.dump.enabled': True,
-                          # Allow installing extensions dropped into the profile folder
-                          'extensions.autoDisableScopes': 10,
-                          # Don't open a dialog to show available add-on updates
-                          'extensions.update.notifyUser' : False,
-                        }
-  syncVerRe = re.compile(
-      r"Sync version: (?P<syncversion>.*)\n")
-  ffVerRe = re.compile(
-      r"Firefox version: (?P<ffver>.*)\n")
-  ffDateRe = re.compile(
-      r"Firefox builddate: (?P<ffdate>.*)\n")
-
-  def __init__(self, extensionDir,
-               testfile="sync.test",
-               binary=None, config=None, rlock=None, mobile=False,
-               logfile="tps.log", resultfile="tps_result.json",
-               ignore_unused_engines=False):
-    self.extensions = []
-    self.testfile = testfile
-    self.logfile = os.path.abspath(logfile)
-    self.resultfile = resultfile
-    self.binary = binary
-    self.ignore_unused_engines = ignore_unused_engines
-    self.config = config if config else {}
-    self.repo = None
-    self.changeset = None
-    self.branch = None
-    self.numfailed = 0
-    self.numpassed = 0
-    self.nightly = False
-    self.rlock = rlock
-    self.mobile = mobile
-    self.tpsxpi = None
-    self.firefoxRunner = None
-    self.extensionDir = extensionDir
-    self.productversion = None
-    self.addonversion = None
-    self.postdata = {}
-    self.errorlogs = {}
-
-  @property
-  def mobile(self):
-    return self._mobile
-
-  @mobile.setter
-  def mobile(self, value):
-    self._mobile = value
-    self.synctype = 'desktop' if not self._mobile else 'mobile'
-
-  def log(self, msg, printToConsole=False):
-    """Appends a string to the logfile"""
-
-    f = open(self.logfile, 'a')
-    f.write(msg)
-    f.close()
-    if printToConsole:
-      print msg
-
-  def writeToResultFile(self, postdata, body=None,
-                        sendTo=['crossweave@mozilla.com']):
-    """Writes results to test file"""
-
-    results = {'results': []}
+    default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
+                    'GNOME_DISABLE_CRASH_DIALOG': '1',
+                    'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
+                    'MOZ_NO_REMOTE': '1',
+                    'XPCOM_DEBUG_BREAK': 'warn',
+                  }
+    default_preferences = { 'app.update.enabled' : False,
+                            'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
+                            'extensions.update.enabled'    : False,
+                            'extensions.update.notifyUser' : False,
+                            'browser.shell.checkDefaultBrowser' : False,
+                            'browser.tabs.warnOnClose' : False,
+                            'browser.warnOnQuit': False,
+                            'browser.sessionstore.resume_from_crash': False,
+                            'services.sync.addons.ignoreRepositoryChecking': True,
+                            'services.sync.firstSync': 'notReady',
+                            'services.sync.lastversion': '1.0',
+                            'services.sync.log.rootLogger': 'Trace',
+                            'services.sync.log.logger.engine.addons': 'Trace',
+                            'services.sync.log.logger.service.main': 'Trace',
+                            'services.sync.log.logger.engine.bookmarks': 'Trace',
+                            'services.sync.log.appender.console': 'Trace',
+                            'services.sync.log.appender.debugLog.enabled': True,
+                            'toolkit.startup.max_resumed_crashes': -1,
+                            'browser.dom.window.dump.enabled': True,
+                            # Allow installing extensions dropped into the profile folder
+                            'extensions.autoDisableScopes': 10,
+                            # Don't open a dialog to show available add-on updates
+                            'extensions.update.notifyUser' : False,
+                          }
+    syncVerRe = re.compile(
+        r"Sync version: (?P<syncversion>.*)\n")
+    ffVerRe = re.compile(
+        r"Firefox version: (?P<ffver>.*)\n")
+    ffDateRe = re.compile(
+        r"Firefox builddate: (?P<ffdate>.*)\n")
 
-    if os.access(self.resultfile, os.F_OK):
-      f = open(self.resultfile, 'r')
-      results = json.loads(f.read())
-      f.close()
-
-    f = open(self.resultfile, 'w')
-    if body is not None:
-      postdata['body'] = body
-    if self.numpassed is not None:
-      postdata['numpassed'] = self.numpassed
-    if self.numfailed is not None:
-      postdata['numfailed'] = self.numfailed
-    if self.firefoxRunner and self.firefoxRunner.url:
-      postdata['firefoxrunnerurl'] = self.firefoxRunner.url
-
-    postdata['sendTo'] = sendTo
-    results['results'].append(postdata)
-    f.write(json.dumps(results, indent=2))
-    f.close()
+    def __init__(self, extensionDir,
+                 testfile="sync.test",
+                 binary=None, config=None, rlock=None, mobile=False,
+                 logfile="tps.log", resultfile="tps_result.json",
+                 ignore_unused_engines=False):
+        self.extensions = []
+        self.testfile = testfile
+        self.logfile = os.path.abspath(logfile)
+        self.resultfile = resultfile
+        self.binary = binary
+        self.ignore_unused_engines = ignore_unused_engines
+        self.config = config if config else {}
+        self.repo = None
+        self.changeset = None
+        self.branch = None
+        self.numfailed = 0
+        self.numpassed = 0
+        self.nightly = False
+        self.rlock = rlock
+        self.mobile = mobile
+        self.tpsxpi = None
+        self.firefoxRunner = None
+        self.extensionDir = extensionDir
+        self.productversion = None
+        self.addonversion = None
+        self.postdata = {}
+        self.errorlogs = {}
 
-  def _zip_add_file(self, zip, file, rootDir):
-    zip.write(os.path.join(rootDir, file), file)
+    @property
+    def mobile(self):
+        return self._mobile
 
-  def _zip_add_dir(self, zip, dir, rootDir):
-    try:
-      zip.write(os.path.join(rootDir, dir), dir)
-    except:
-      # on some OS's, adding directory entries doesn't seem to work
-      pass
-    for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
-      for f in files:
-        zip.write(os.path.join(root, f), os.path.join(dir, f))
+    @mobile.setter
+    def mobile(self, value):
+        self._mobile = value
+        self.synctype = 'desktop' if not self._mobile else 'mobile'
 
-  def run_single_test(self, testdir, testname):
-    testpath = os.path.join(testdir, testname)
-    self.log("Running test %s\n" % testname)
-
-    # Create a random account suffix that is used when creating test
-    # accounts on a staging server.
-    account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
-                                                 for i in range(1,6)])}
-    self.config['account'].update(account_suffix)
+    def log(self, msg, printToConsole=False):
+        """Appends a string to the logfile"""
 
-    # Read and parse the test file, merge it with the contents of the config
-    # file, and write the combined output to a temporary file.
-    f = open(testpath, 'r')
-    testcontent = f.read()
-    f.close()
-    try:
-      test = json.loads(testcontent)
-    except:
-      test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
+        f = open(self.logfile, 'a')
+        f.write(msg)
+        f.close()
+        if printToConsole:
+            print msg
 
-    testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
-    testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
+    def writeToResultFile(self, postdata, body=None,
+                          sendTo=['crossweave@mozilla.com']):
+        """Writes results to test file"""
 
-    tmpfile = TempFile(prefix='tps_test_')
-    tmpfile.write(testcontent)
-    tmpfile.close()
+        results = {'results': []}
 
-    # generate the profiles defined in the test, and a list of test phases
-    profiles = {}
-    phaselist = []
-    for phase in test:
-      profilename = test[phase]
+        if os.access(self.resultfile, os.F_OK):
+            f = open(self.resultfile, 'r')
+            results = json.loads(f.read())
+            f.close()
 
-      # create the profile if necessary
-      if not profilename in profiles:
-        profiles[profilename] = Profile(preferences = self.preferences,
-                                        addons = self.extensions)
+        f = open(self.resultfile, 'w')
+        if body is not None:
+            postdata['body'] = body
+        if self.numpassed is not None:
+            postdata['numpassed'] = self.numpassed
+        if self.numfailed is not None:
+            postdata['numfailed'] = self.numfailed
+        if self.firefoxRunner and self.firefoxRunner.url:
+            postdata['firefoxrunnerurl'] = self.firefoxRunner.url
 
-      # create the test phase
-      phaselist.append(TPSTestPhase(
-          phase,
-          profiles[profilename],
-          testname,
-          tmpfile.filename,
-          self.logfile,
-          self.env,
-          self.firefoxRunner,
-          self.log,
-          ignore_unused_engines=self.ignore_unused_engines))
+        postdata['sendTo'] = sendTo
+        results['results'].append(postdata)
+        f.write(json.dumps(results, indent=2))
+        f.close()
+
+    def _zip_add_file(self, zip, file, rootDir):
+        zip.write(os.path.join(rootDir, file), file)
 
-    # sort the phase list by name
-    phaselist = sorted(phaselist, key=lambda phase: phase.phase)
-
-    # run each phase in sequence, aborting at the first failure
-    for phase in phaselist:
-      phase.run()
-
-      # if a failure occurred, dump the entire sync log into the test log
-      if phase.status != "PASS":
-        for profile in profiles:
-          self.log("\nDumping sync log for profile %s\n" %  profiles[profile].profile)
-          for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
+    def _zip_add_dir(self, zip, dir, rootDir):
+        try:
+            zip.write(os.path.join(rootDir, dir), dir)
+        except:
+            # on some OS's, adding directory entries doesn't seem to work
+            pass
+        for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
             for f in files:
-              weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
-              if os.access(weavelog, os.F_OK):
-                with open(weavelog, 'r') as fh:
-                  for line in fh:
-                    possible_time = line[0:13]
-                    if len(possible_time) == 13 and possible_time.isdigit():
-                      time_ms = int(possible_time)
-                      formatted = time.strftime('%Y-%m-%d %H:%M:%S',
-                              time.localtime(time_ms / 1000))
-                      self.log('%s.%03d %s' % (
-                          formatted, time_ms % 1000, line[14:] ))
-                    else:
-                      self.log(line)
-        break;
+                zip.write(os.path.join(root, f), os.path.join(dir, f))
+
+    def run_single_test(self, testdir, testname):
+        testpath = os.path.join(testdir, testname)
+        self.log("Running test %s\n" % testname)
+
+        # Create a random account suffix that is used when creating test
+        # accounts on a staging server.
+        account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
+                                                     for i in range(1,6)])}
+        self.config['account'].update(account_suffix)
+
+        # Read and parse the test file, merge it with the contents of the config
+        # file, and write the combined output to a temporary file.
+        f = open(testpath, 'r')
+        testcontent = f.read()
+        f.close()
+        try:
+            test = json.loads(testcontent)
+        except:
+            test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
+
+        testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
+        testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
+
+        tmpfile = TempFile(prefix='tps_test_')
+        tmpfile.write(testcontent)
+        tmpfile.close()
 
-    # grep the log for FF and sync versions
-    f = open(self.logfile)
-    logdata = f.read()
-    match = self.syncVerRe.search(logdata)
-    sync_version = match.group("syncversion") if match else 'unknown'
-    match = self.ffVerRe.search(logdata)
-    firefox_version = match.group("ffver") if match else 'unknown'
-    match = self.ffDateRe.search(logdata)
-    firefox_builddate = match.group("ffdate") if match else 'unknown'
-    f.close()
-    if phase.status == 'PASS':
-      logdata = ''
-    else:
-      # we only care about the log data for this specific test
-      logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
+        # generate the profiles defined in the test, and a list of test phases
+        profiles = {}
+        phaselist = []
+        for phase in test:
+            profilename = test[phase]
+
+            # create the profile if necessary
+            if not profilename in profiles:
+                profiles[profilename] = Profile(preferences = self.preferences,
+                                                addons = self.extensions)
 
-    result = {
-      'PASS': lambda x: ('TEST-PASS', ''),
-      'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
-      'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
-    } [phase.status](phase.errline)
-    logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
+            # create the test phase
+            phaselist.append(TPSTestPhase(
+                phase,
+                profiles[profilename],
+                testname,
+                tmpfile.filename,
+                self.logfile,
+                self.env,
+                self.firefoxRunner,
+                self.log,
+                ignore_unused_engines=self.ignore_unused_engines))
 
-    try:
-      repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
-    except:
-      repoinfo = {}
-    apprepo = repoinfo.get('application_repository', '')
-    appchangeset = repoinfo.get('application_changeset', '')
+        # sort the phase list by name
+        phaselist = sorted(phaselist, key=lambda phase: phase.phase)
+
+        # run each phase in sequence, aborting at the first failure
+        for phase in phaselist:
+            phase.run()
 
-    # save logdata to a temporary file for posting to the db
-    tmplogfile = None
-    if logdata:
-      tmplogfile = TempFile(prefix='tps_log_')
-      tmplogfile.write(logdata)
-      tmplogfile.close()
-      self.errorlogs[testname] = tmplogfile
+            # if a failure occurred, dump the entire sync log into the test log
+            if phase.status != "PASS":
+                for profile in profiles:
+                    self.log("\nDumping sync log for profile %s\n" %  profiles[profile].profile)
+                    for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
+                        for f in files:
+                            weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
+                            if os.access(weavelog, os.F_OK):
+                                with open(weavelog, 'r') as fh:
+                                    for line in fh:
+                                        possible_time = line[0:13]
+                                        if len(possible_time) == 13 and possible_time.isdigit():
+                                            time_ms = int(possible_time)
+                                            formatted = time.strftime('%Y-%m-%d %H:%M:%S',
+                                                    time.localtime(time_ms / 1000))
+                                            self.log('%s.%03d %s' % (
+                                                formatted, time_ms % 1000, line[14:] ))
+                                        else:
+                                            self.log(line)
+                break;
 
-    resultdata = ({ "productversion": { "version": firefox_version,
-                                        "buildid": firefox_builddate,
-                                        "builddate": firefox_builddate[0:8],
-                                        "product": "Firefox",
-                                        "repository": apprepo,
-                                        "changeset": appchangeset,
-                                      },
-                    "addonversion": { "version": sync_version,
-                                      "product": "Firefox Sync" },
-                    "name": testname,
-                    "message": result[1],
-                    "state": result[0],
-                    "logdata": logdata
-                  })
+        # grep the log for FF and sync versions
+        f = open(self.logfile)
+        logdata = f.read()
+        match = self.syncVerRe.search(logdata)
+        sync_version = match.group("syncversion") if match else 'unknown'
+        match = self.ffVerRe.search(logdata)
+        firefox_version = match.group("ffver") if match else 'unknown'
+        match = self.ffDateRe.search(logdata)
+        firefox_builddate = match.group("ffdate") if match else 'unknown'
+        f.close()
+        if phase.status == 'PASS':
+            logdata = ''
+        else:
+            # we only care about the log data for this specific test
+            logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
 
-    self.log(logstr, True)
-    for phase in phaselist:
-      print "\t%s: %s" % (phase.phase, phase.status)
-      if phase.status == 'FAIL':
-        break
+        result = {
+          'PASS': lambda x: ('TEST-PASS', ''),
+          'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
+          'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
+        } [phase.status](phase.errline)
+        logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
 
-    return resultdata
-
-  def run_tests(self):
-    # delete the logfile if it already exists
-    if os.access(self.logfile, os.F_OK):
-      os.remove(self.logfile)
+        try:
+            repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
+        except:
+            repoinfo = {}
+        apprepo = repoinfo.get('application_repository', '')
+        appchangeset = repoinfo.get('application_changeset', '')
 
-    # Make a copy of the default env variables and preferences, and update
-    # them for mobile settings if needed.
-    self.env = self.default_env.copy()
-    self.preferences = self.default_preferences.copy()
-    if self.mobile:
-      self.preferences.update({'services.sync.client.type' : 'mobile'})
+        # save logdata to a temporary file for posting to the db
+        tmplogfile = None
+        if logdata:
+            tmplogfile = TempFile(prefix='tps_log_')
+            tmplogfile.write(logdata)
+            tmplogfile.close()
+            self.errorlogs[testname] = tmplogfile
 
-    # Acquire a lock to make sure no other threads are running tests
-    # at the same time.
-    if self.rlock:
-      self.rlock.acquire()
-
-    try:
-      # Create the Firefox runner, which will download and install the
-      # build, as needed.
-      if not self.firefoxRunner:
-        self.firefoxRunner = TPSFirefoxRunner(self.binary)
+        resultdata = ({ "productversion": { "version": firefox_version,
+                                            "buildid": firefox_builddate,
+                                            "builddate": firefox_builddate[0:8],
+                                            "product": "Firefox",
+                                            "repository": apprepo,
+                                            "changeset": appchangeset,
+                                          },
+                        "addonversion": { "version": sync_version,
+                                          "product": "Firefox Sync" },
+                        "name": testname,
+                        "message": result[1],
+                        "state": result[0],
+                        "logdata": logdata
+                      })
 
-      # now, run the test group
-      self.run_test_group()
+        self.log(logstr, True)
+        for phase in phaselist:
+            print "\t%s: %s" % (phase.phase, phase.status)
+            if phase.status == 'FAIL':
+                break
+
+        return resultdata
+
+    def run_tests(self):
+        # delete the logfile if it already exists
+        if os.access(self.logfile, os.F_OK):
+            os.remove(self.logfile)
 
-    except:
-      traceback.print_exc()
-      self.numpassed = 0
-      self.numfailed = 1
-      try:
-        self.writeToResultFile(self.postdata,
-                               '<pre>%s</pre>' % traceback.format_exc())
-      except:
-        traceback.print_exc()
-    else:
-      try:
+        # Make a copy of the default env variables and preferences, and update
+        # them for mobile settings if needed.
+        self.env = self.default_env.copy()
+        self.preferences = self.default_preferences.copy()
+        if self.mobile:
+            self.preferences.update({'services.sync.client.type' : 'mobile'})
 
-        if self.numfailed > 0 or self.numpassed == 0:
-          To = self.config['email'].get('notificationlist')
-        else:
-          To = self.config['email'].get('passednotificationlist')
-        self.writeToResultFile(self.postdata,
-                               sendTo=To)
-      except:
-        traceback.print_exc()
+        # Acquire a lock to make sure no other threads are running tests
+        # at the same time.
+        if self.rlock:
+            self.rlock.acquire()
+
         try:
-          self.writeToResultFile(self.postdata,
-                                 '<pre>%s</pre>' % traceback.format_exc())
-        except:
-          traceback.print_exc()
+            # Create the Firefox runner, which will download and install the
+            # build, as needed.
+            if not self.firefoxRunner:
+                self.firefoxRunner = TPSFirefoxRunner(self.binary)
 
-    # release our lock
-    if self.rlock:
-      self.rlock.release()
+            # now, run the test group
+            self.run_test_group()
 
-    # dump out a summary of test results
-    print 'Test Summary\n'
-    for test in self.postdata.get('tests', {}):
-      print '%s | %s | %s' % (test['state'], test['name'], test['message'])
-
-  def run_test_group(self):
-    self.results = []
-    self.extensions = []
+        except:
+            traceback.print_exc()
+            self.numpassed = 0
+            self.numfailed = 1
+            try:
+                self.writeToResultFile(self.postdata,
+                                       '<pre>%s</pre>' % traceback.format_exc())
+            except:
+                traceback.print_exc()
+        else:
+            try:
 
-    # set the OS we're running on
-    os_string = platform.uname()[2] + " " + platform.uname()[3]
-    if os_string.find("Darwin") > -1:
-      os_string = "Mac OS X " + platform.mac_ver()[0]
-    if platform.uname()[0].find("Linux") > -1:
-      os_string = "Linux " + platform.uname()[5]
-    if platform.uname()[0].find("Win") > -1:
-      os_string = "Windows " + platform.uname()[3]
+                if self.numfailed > 0 or self.numpassed == 0:
+                    To = self.config['email'].get('notificationlist')
+                else:
+                    To = self.config['email'].get('passednotificationlist')
+                self.writeToResultFile(self.postdata,
+                                       sendTo=To)
+            except:
+                traceback.print_exc()
+                try:
+                    self.writeToResultFile(self.postdata,
+                                           '<pre>%s</pre>' % traceback.format_exc())
+                except:
+                    traceback.print_exc()
+
+        # release our lock
+        if self.rlock:
+            self.rlock.release()
 
-    # reset number of passed/failed tests
-    self.numpassed = 0
-    self.numfailed = 0
+        # dump out a summary of test results
+        print 'Test Summary\n'
+        for test in self.postdata.get('tests', {}):
+            print '%s | %s | %s' % (test['state'], test['name'], test['message'])
 
-    # build our tps.xpi extension
-    self.extensions.append(os.path.join(self.extensionDir, 'tps'))
-    self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
+    def run_test_group(self):
+        self.results = []
+        self.extensions = []
 
-    # build the test list
-    try:
-      f = open(self.testfile)
-      jsondata = f.read()
-      f.close()
-      testfiles = json.loads(jsondata)
-      testlist = testfiles['tests']
-    except ValueError:
-      testlist = [os.path.basename(self.testfile)]
-    testdir = os.path.dirname(self.testfile)
+        # set the OS we're running on
+        os_string = platform.uname()[2] + " " + platform.uname()[3]
+        if os_string.find("Darwin") > -1:
+            os_string = "Mac OS X " + platform.mac_ver()[0]
+        if platform.uname()[0].find("Linux") > -1:
+            os_string = "Linux " + platform.uname()[5]
+        if platform.uname()[0].find("Win") > -1:
+            os_string = "Windows " + platform.uname()[3]
 
-    self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
-    self.mozhttpd.start()
+        # reset number of passed/failed tests
+        self.numpassed = 0
+        self.numfailed = 0
+
+        # build our tps.xpi extension
+        self.extensions.append(os.path.join(self.extensionDir, 'tps'))
+        self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
 
-    # run each test, and save the results
-    for test in testlist:
-      result = self.run_single_test(testdir, test)
+        # build the test list
+        try:
+            f = open(self.testfile)
+            jsondata = f.read()
+            f.close()
+            testfiles = json.loads(jsondata)
+            testlist = testfiles['tests']
+        except ValueError:
+            testlist = [os.path.basename(self.testfile)]
+        testdir = os.path.dirname(self.testfile)
 
-      if not self.productversion:
-        self.productversion = result['productversion']
-      if not self.addonversion:
-        self.addonversion = result['addonversion']
+        self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
+        self.mozhttpd.start()
+
+        # run each test, and save the results
+        for test in testlist:
+            result = self.run_single_test(testdir, test)
 
-      self.results.append({'state': result['state'], 
-                           'name': result['name'], 
-                           'message': result['message'],
-                           'logdata': result['logdata']})
-      if result['state'] == 'TEST-PASS':
-        self.numpassed += 1
-      else:
-        self.numfailed += 1
+            if not self.productversion:
+                self.productversion = result['productversion']
+            if not self.addonversion:
+                self.addonversion = result['addonversion']
 
-    self.mozhttpd.stop()
+            self.results.append({'state': result['state'],
+                                 'name': result['name'],
+                                 'message': result['message'],
+                                 'logdata': result['logdata']})
+            if result['state'] == 'TEST-PASS':
+                self.numpassed += 1
+            else:
+                self.numfailed += 1
 
-    # generate the postdata we'll use to post the results to the db
-    self.postdata = { 'tests': self.results, 
-                      'os':os_string,
-                      'testtype': 'crossweave',
-                      'productversion': self.productversion,
-                      'addonversion': self.addonversion,
-                      'synctype': self.synctype,
-                    }
+        self.mozhttpd.stop()
+
+        # generate the postdata we'll use to post the results to the db
+        self.postdata = { 'tests': self.results,
+                          'os':os_string,
+                          'testtype': 'crossweave',
+                          'productversion': self.productversion,
+                          'addonversion': self.addonversion,
+                          'synctype': self.synctype,
+                        }
--- a/testing/tps/tps/thread.py
+++ b/testing/tps/tps/thread.py
@@ -3,62 +3,62 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from threading import Thread
 
 from testrunner import TPSTestRunner
 
 class TPSTestThread(Thread):
 
-  def __init__(self, extensionDir, builddata=None,
-               testfile=None, logfile=None, rlock=None, config=None):
-    assert(builddata)
-    assert(config)
-    self.extensionDir = extensionDir
-    self.builddata = builddata
-    self.testfile = testfile
-    self.logfile = logfile
-    self.rlock = rlock
-    self.config = config
-    Thread.__init__(self)
+    def __init__(self, extensionDir, builddata=None,
+                 testfile=None, logfile=None, rlock=None, config=None):
+        assert(builddata)
+        assert(config)
+        self.extensionDir = extensionDir
+        self.builddata = builddata
+        self.testfile = testfile
+        self.logfile = logfile
+        self.rlock = rlock
+        self.config = config
+        Thread.__init__(self)
 
-  def run(self):
-    # run the tests in normal mode ...
-    TPS = TPSTestRunner(self.extensionDir,
-                        testfile=self.testfile,
-                        logfile=self.logfile,
-                        binary=self.builddata['buildurl'],
-                        config=self.config,
-                        rlock=self.rlock,
-                        mobile=False)
-    TPS.run_tests()
+    def run(self):
+        # run the tests in normal mode ...
+        TPS = TPSTestRunner(self.extensionDir,
+                            testfile=self.testfile,
+                            logfile=self.logfile,
+                            binary=self.builddata['buildurl'],
+                            config=self.config,
+                            rlock=self.rlock,
+                            mobile=False)
+        TPS.run_tests()
 
-    # Get the binary used by this TPS instance, and use it in subsequent
-    # ones, so it doesn't have to be re-downloaded each time.
-    binary = TPS.firefoxRunner.binary
+        # Get the binary used by this TPS instance, and use it in subsequent
+        # ones, so it doesn't have to be re-downloaded each time.
+        binary = TPS.firefoxRunner.binary
 
-    # ... and then again in mobile mode
-    TPS_mobile = TPSTestRunner(self.extensionDir,
-                               testfile=self.testfile,
-                               logfile=self.logfile,
-                               binary=binary,
-                               config=self.config,
-                               rlock=self.rlock,
-                               mobile=True)
-    TPS_mobile.run_tests()
+        # ... and then again in mobile mode
+        TPS_mobile = TPSTestRunner(self.extensionDir,
+                                   testfile=self.testfile,
+                                   logfile=self.logfile,
+                                   binary=binary,
+                                   config=self.config,
+                                   rlock=self.rlock,
+                                   mobile=True)
+        TPS_mobile.run_tests()
 
-    # ... and again via the staging server, if credentials are present
-    stageaccount = self.config.get('stageaccount')
-    if stageaccount:
-      username = stageaccount.get('username')
-      password = stageaccount.get('password')
-      passphrase = stageaccount.get('passphrase')
-      if username and password and passphrase:
-        stageconfig = self.config.copy()
-        stageconfig['account'] = stageaccount.copy()
-        TPS_stage = TPSTestRunner(self.extensionDir,
-                                  testfile=self.testfile,
-                                  logfile=self.logfile,
-                                  binary=binary,
-                                  config=stageconfig,
-                                  rlock=self.rlock,
-                                  mobile=False)#, autolog=self.autolog)
-        TPS_stage.run_tests()
+        # ... and again via the staging server, if credentials are present
+        stageaccount = self.config.get('stageaccount')
+        if stageaccount:
+            username = stageaccount.get('username')
+            password = stageaccount.get('password')
+            passphrase = stageaccount.get('passphrase')
+            if username and password and passphrase:
+                stageconfig = self.config.copy()
+                stageconfig['account'] = stageaccount.copy()
+                TPS_stage = TPSTestRunner(self.extensionDir,
+                                          testfile=self.testfile,
+                                          logfile=self.logfile,
+                                          binary=binary,
+                                          config=stageconfig,
+                                          rlock=self.rlock,
+                                          mobile=False)#, autolog=self.autolog)
+                TPS_stage.run_tests()