Backed out 6 changesets (bug 1506928) for android tp6m-1 raptor 'max time exceeded' failures.
authorBrindusan Cristian <cbrindusan@mozilla.com>
Wed, 17 Apr 2019 18:02:44 +0300
changeset 528844 f478c61c1bc94b243822b468d7d57116f4298e9d
parent 528843 1583103d97154b393fe7808be1ce65220c6aef49
child 528845 10e39089de4eae107554300619c34fdcc18ae9d3
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1506928
milestone68.0a1
backs out98c7524647ae009fc69e434ef8dddd2c3fb72e81
097b31242a5abad203858c7c0f3a2ea96e09ad8c
120d7d8970e5ad9a891adf7ff0516f5aaed67d6c
9ca5edb93d09b69fa866e9ca42c7bdb38ecf2d65
ab985d0cbffd4602bbbd513b8717c53879ef7933
6ad35d665d4b843f340b7f90e4b858a74866e505
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
Backed out 6 changesets (bug 1506928) for android tp6m-1 raptor 'max time exceeded' failures. Backed out changeset 98c7524647ae (bug 1506928) Backed out changeset 097b31242a5a (bug 1506928) Backed out changeset 120d7d8970e5 (bug 1506928) Backed out changeset 9ca5edb93d09 (bug 1506928) Backed out changeset ab985d0cbffd (bug 1506928) Backed out changeset 6ad35d665d4b (bug 1506928)
testing/mozharness/mozharness/base/script.py
testing/raptor/raptor/output.py
testing/raptor/raptor/raptor.py
--- a/testing/mozharness/mozharness/base/script.py
+++ b/testing/mozharness/mozharness/base/script.py
@@ -1451,24 +1451,16 @@ class ScriptMixin(PlatformMixin):
                         """Avoid losing the final lines of the log?"""
                         loop = False
                     while True:
                         line = p.stdout.readline()
                         if not line:
                             break
                         parser.add_lines(line)
                 returncode = p.returncode
-        except KeyboardInterrupt:
-            level = error_level
-            if halt_on_failure:
-                level = FATAL
-            self.log("Process interrupted by the user, killing process with pid %s" % p.pid,
-                     level=level)
-            p.kill()
-            return -1
         except OSError, e:
             level = error_level
             if halt_on_failure:
                 level = FATAL
             self.log('caught OS error %s: %s while running %s' % (e.errno,
                      e.strerror, command), level=level)
             return -1
 
--- a/testing/raptor/raptor/output.py
+++ b/testing/raptor/raptor/output.py
@@ -731,17 +731,17 @@ class Output(object):
                         screenshot['screenshot'],
                         screenshot['test_name'],
                         screenshot['page_cycle']))
 
         self.summarized_screenshots.append("""</table></body> </html>""")
 
     def output(self, test_names):
         """output to file and perfherder data json """
-        if os.getenv('MOZ_UPLOAD_DIR'):
+        if os.environ['MOZ_UPLOAD_DIR']:
             # i.e. testing/mozharness/build/raptor.json locally; in production it will
             # be at /tasks/task_*/build/ (where it will be picked up by mozharness later
             # and made into a tc artifact accessible in treeherder as perfherder-data.json)
             results_path = os.path.join(os.path.dirname(os.environ['MOZ_UPLOAD_DIR']),
                                         'raptor.json')
             screenshot_path = os.path.join(os.path.dirname(os.environ['MOZ_UPLOAD_DIR']),
                                            'screenshots.html')
         else:
--- a/testing/raptor/raptor/raptor.py
+++ b/testing/raptor/raptor/raptor.py
@@ -1,37 +1,34 @@
 #!/usr/bin/env python
 
 # 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/.
-
 from __future__ import absolute_import
 
 import json
 import os
 import posixpath
 import shutil
-import signal
 import sys
 import tempfile
 import time
 
 import mozcrash
 import mozinfo
 from mozdevice import ADBDevice
 from mozlog import commandline, get_default_logger
 from mozprofile import create_profile
-from mozproxy import get_playback
 from mozrunner import runners
 
 # need this so raptor imports work both from /raptor and via mach
 here = os.path.abspath(os.path.dirname(__file__))
 paths = [here]
-if os.environ.get('SCRIPTSPATH') is not None:
+if os.environ.get('SCRIPTSPATH', None) is not None:
     # in production it is env SCRIPTS_PATH
     paths.append(os.environ['SCRIPTSPATH'])
 else:
     # locally it's in source tree
     paths.append(os.path.join(here, '..', '..', 'mozharness'))
 
 webext_dir = os.path.join(here, '..', 'webext')
 paths.append(webext_dir)
@@ -48,78 +45,62 @@ try:
 except ImportError:
     build = None
 
 from benchmark import Benchmark
 from cmdline import (parse_args,
                      FIREFOX_ANDROID_APPS,
                      CHROMIUM_DISTROS)
 from control_server import RaptorControlServer
-from gecko_profile import GeckoProfile
 from gen_test_config import gen_test_config
 from outputhandler import OutputHandler
 from manifest import get_raptor_test_list
+from mozproxy import get_playback
+from results import RaptorResultsHandler
+from gecko_profile import GeckoProfile
 from power import init_android_power_test, finish_android_power_test
-from results import RaptorResultsHandler
 from utils import view_gecko_profile
 
 
-class SignalHandler:
-
-    def __init__(self):
-        signal.signal(signal.SIGINT, self.handle_signal)
-        signal.signal(signal.SIGTERM, self.handle_signal)
-
-    def handle_signal(self, signum, frame):
-        raise SignalHandlerException("Program aborted due to signal %s" % signum)
-
-
-class SignalHandlerException(Exception):
-    pass
-
-
 class Raptor(object):
     """Container class for Raptor"""
 
     def __init__(self, app, binary, run_local=False, obj_path=None,
                  gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
                  symbols_path=None, host=None, power_test=False, is_release_build=False,
-                 debug_mode=False, post_startup_delay=None, interrupt_handler=None, **kwargs):
+                 debug_mode=False, post_startup_delay=None, activity=None):
 
         # Override the magic --host HOST_IP with the value of the environment variable.
         if host == 'HOST_IP':
             host = os.environ['HOST_IP']
-
-        self.config = {
-            'app': app,
-            'binary': binary,
-            'platform': mozinfo.os,
-            'run_local': run_local,
-            'obj_path': obj_path,
-            'gecko_profile': gecko_profile,
-            'gecko_profile_interval': gecko_profile_interval,
-            'gecko_profile_entries': gecko_profile_entries,
-            'symbols_path': symbols_path,
-            'host': host,
-            'power_test': power_test,
-            'is_release_build': is_release_build,
-        }
-
+        self.config = {}
+        self.config['app'] = app
+        self.config['binary'] = binary
+        self.config['platform'] = mozinfo.os
+        self.config['processor'] = mozinfo.processor
+        self.config['run_local'] = run_local
+        self.config['obj_path'] = obj_path
+        self.config['gecko_profile'] = gecko_profile
+        self.config['gecko_profile_interval'] = gecko_profile_interval
+        self.config['gecko_profile_entries'] = gecko_profile_entries
+        self.config['symbols_path'] = symbols_path
+        self.config['host'] = host
+        self.config['power_test'] = power_test
+        self.config['is_release_build'] = is_release_build
         self.raptor_venv = os.path.join(os.getcwd(), 'raptor-venv')
         self.log = get_default_logger(component='raptor-main')
         self.control_server = None
         self.playback = None
         self.benchmark = None
         self.benchmark_port = 0
         self.gecko_profiler = None
         self.post_startup_delay = post_startup_delay
         self.device = None
         self.profile_class = app
         self.firefox_android_apps = FIREFOX_ANDROID_APPS
-        self.interrupt_handler = interrupt_handler
 
         # debug mode is currently only supported when running locally
         self.debug_mode = debug_mode if self.config['run_local'] else False
 
         # if running debug-mode reduce the pause after browser startup
         if self.debug_mode:
             self.post_startup_delay = min(self.post_startup_delay, 3000)
             self.log.info("debug-mode enabled, reducing post-browser startup pause to %d ms"
@@ -133,66 +114,65 @@ class Raptor(object):
     @property
     def profile_data_dir(self):
         if 'MOZ_DEVELOPER_REPO_DIR' in os.environ:
             return os.path.join(os.environ['MOZ_DEVELOPER_REPO_DIR'], 'testing', 'profiles')
         if build:
             return os.path.join(build.topsrcdir, 'testing', 'profiles')
         return os.path.join(here, 'profile_data')
 
-    def check_for_crashes(self):
-        raise NotImplementedError
-
     def run_test_setup(self, test):
         self.log.info("starting raptor test: %s" % test['name'])
         self.log.info("test settings: %s" % str(test))
         self.log.info("raptor config: %s" % str(self.config))
 
         if test.get('type') == "benchmark":
             self.serve_benchmark_source(test)
 
-        gen_test_config(
-            self.config['app'],
-            test['name'],
-            self.control_server.port,
-            self.post_startup_delay,
-            host=self.config['host'],
-            b_port=self.benchmark_port,
-            debug_mode=1 if self.debug_mode else 0,
-            browser_cycle=test.get('browser_cycle', 1),
-            )
+        gen_test_config(self.config['app'],
+                        test['name'],
+                        self.control_server.port,
+                        self.post_startup_delay,
+                        host=self.config['host'],
+                        b_port=self.benchmark_port,
+                        debug_mode=1 if self.debug_mode else 0,
+                        browser_cycle=test.get('browser_cycle', 1))
 
         self.install_raptor_webext()
 
-        if test.get("preferences") is not None:
+        if test.get("preferences", None) is not None:
             self.set_browser_test_prefs(test['preferences'])
 
         # if 'alert_on' was provided in the test INI, add to our config for results/output
-        self.config['subtest_alert_on'] = test.get('alert_on')
+        self.config['subtest_alert_on'] = test.get('alert_on', None)
+
+    def set_browser_test_prefs(self, raw_prefs):
+        # add test specific preferences
+        if self.config['app'] == "firefox":
+            self.log.info("setting test-specific browser preferences")
+            self.profile.set_preferences(json.loads(raw_prefs))
+        else:
+            self.log.info("preferences were configured for the test, however \
+                          we currently do not install them on non Firefox browsers.")
 
     def run_test_teardown(self):
         self.check_for_crashes()
 
         if self.playback is not None:
             self.playback.stop()
 
         self.remove_raptor_webext()
 
         # gecko profiling symbolication
         if self.config['gecko_profile'] is True:
             self.gecko_profiler.symbolicate()
             # clean up the temp gecko profiling folders
             self.log.info("cleaning up after gecko profiling")
             self.gecko_profiler.clean()
 
-    def set_browser_test_prefs(self, raw_prefs):
-        # add test specific preferences
-        self.log.info("preferences were configured for the test, however \
-                        we currently do not install them on non Firefox browsers.")
-
     def create_browser_profile(self):
         self.profile = create_profile(self.profile_class)
 
         # Merge in base profiles
         with open(os.path.join(self.profile_data_dir, 'profiles.json'), 'r') as fh:
             base_profiles = json.load(fh)['raptor']
 
         for name in base_profiles:
@@ -202,40 +182,50 @@ class Raptor(object):
 
         # add profile dir to our config
         self.config['local_profile_dir'] = self.profile.profile
 
     def start_control_server(self):
         self.control_server = RaptorControlServer(self.results_handler, self.debug_mode)
         self.control_server.start()
 
-    def get_playback_config(self, test):
-        platform = self.config['platform']
-        playback_dir = os.path.join(here, 'playback')
+        # for android we must make the control server available to the device
+        if self.config['app'] in self.firefox_android_apps and \
+                self.config['host'] in ('localhost', '127.0.0.1'):
+            self.log.info("making the raptor control server port available to device")
+            _tcp_port = "tcp:%s" % self.control_server.port
+            self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
 
-        self.config.update({
-            'playback_tool': test.get('playback'),
-            'playback_version': test.get('playback_version', "2.0.2"),
-            'playback_binary_zip': test.get('playback_binary_zip_%s' % platform),
-            'playback_pageset_zip': test.get('playback_pageset_zip_%s' % platform),
-            'playback_binary_manifest': test.get('playback_binary_manifest'),
-            'playback_pageset_manifest': test.get('playback_pageset_manifest'),
-        })
+    def get_playback_config(self, test):
+        self.config['playback_tool'] = test.get('playback')
+        self.log.info("test uses playback tool: %s " % self.config['playback_tool'])
+        platform = self.config['platform']
+        self.config['playback_version'] = test.get('playback_version', "2.0.2")
+        self.config['playback_binary_zip'] = test.get('playback_binary_zip_%s' % platform)
+        self.config['playback_pageset_zip'] = test.get('playback_pageset_zip_%s' % platform)
+        playback_dir = os.path.join(here, 'playback')
+        self.config['playback_binary_manifest'] = test.get('playback_binary_manifest')
+        self.config['playback_pageset_manifest'] = test.get('playback_pageset_manifest')
         for key in ('playback_pageset_manifest', 'playback_pageset_zip'):
             if self.config.get(key) is None:
                 continue
             self.config[key] = os.path.join(playback_dir, self.config[key])
 
-        self.log.info("test uses playback tool: %s " % self.config['playback_tool'])
-
     def serve_benchmark_source(self, test):
         # benchmark-type tests require the benchmark test to be served out
         self.benchmark = Benchmark(self.config, test)
         self.benchmark_port = int(self.benchmark.port)
 
+        # for android we must make the benchmarks server available to the device
+        if self.config['app'] in self.firefox_android_apps and \
+                self.config['host'] in ('localhost', '127.0.0.1'):
+            self.log.info("making the raptor benchmarks server port available to device")
+            _tcp_port = "tcp:%s" % self.benchmark_port
+            self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
+
     def install_raptor_webext(self):
         # must intall raptor addon each time because we dynamically update some content
         # the webext is installed into the browser profile
         # note: for chrome the addon is just a list of paths that ultimately are added
         # to the chromium command line '--load-extension' argument
         self.raptor_webext = os.path.join(webext_dir, 'raptor')
         self.log.info("installing webext %s" % self.raptor_webext)
         self.profile.addons.install(self.raptor_webext)
@@ -252,16 +242,24 @@ class Raptor(object):
         if self.config['app'] in ['firefox', 'geckoview', 'fennec', 'refbrow', 'fenix']:
             self.profile.addons.remove_addon(self.webext_id)
 
         # for chrome the addon is just a list (appended to cmd line)
         chrome_apps = CHROMIUM_DISTROS + ["chrome-android", "chromium-android"]
         if self.config['app'] in chrome_apps:
             self.profile.addons.remove(self.raptor_webext)
 
+    def set_test_browser_prefs(self, test_prefs):
+        # if the test has any specific browser prefs specified, set those in browser profiile
+        if self.config['app'] == "firefox":
+            self.profile.set_preferences(json.loads(test_prefs))
+        else:
+            self.log.info("preferences were configured for the test, \
+                          but we do not install them on non Firefox browsers.")
+
     def get_proxy_command_for_mitm(self, test, version):
         # Generate Mitmproxy playback args
         script = os.path.join(here, "playback", "alternate-server-replay-{}.py".format(version))
         recordings = test.get("playback_recordings")
         if recordings:
             recording_paths = []
             proxy_dir = self.playback.mozproxy_dir
             for recording in recordings.split():
@@ -294,16 +292,23 @@ class Raptor(object):
         self.get_playback_config(test)
         self.playback = get_playback(self.config, self.device)
 
         self.get_proxy_command_for_mitm(test, self.config['playback_version'])
 
         # let's start it!
         self.playback.start()
 
+        # for android we must make the playback server available to the device
+        if self.config['app'] in self.firefox_android_apps and self.config['host'] \
+                in ('localhost', '127.0.0.1'):
+            self.log.info("making the raptor playback server port available to device")
+            _tcp_port = "tcp:8080"
+            self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
+
     def delete_proxy_settings_from_profile(self):
         # Must delete the proxy settings from the profile if running
         # the test with a host different from localhost.
         userjspath = os.path.join(self.profile.profile, 'user.js')
         with open(userjspath) as userjsfile:
             prefs = userjsfile.readlines()
         prefs = [pref for pref in prefs if 'network.proxy' not in pref]
         with open(userjspath, 'w') as userjsfile:
@@ -356,96 +361,102 @@ class Raptor(object):
         self.config['raptor_json_path'] = raptor_json_path
         return self.results_handler.summarize_and_output(self.config, test_names)
 
     def get_page_timeout_list(self):
         return self.results_handler.page_timeout_list
 
     def clean_up(self):
         self.control_server.stop()
+        if self.config['app'] not in self.firefox_android_apps:
+            self.runner.stop()
+        elif self.config['app'] in self.firefox_android_apps:
+            self.log.info('removing reverse socket connections')
+            self.device.remove_socket_connections('reverse')
+        else:
+            pass
         self.log.info("finished")
 
 
 class RaptorDesktop(Raptor):
+    def __init__(self, app, binary, run_local=False, obj_path=None,
+                 gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
+                 symbols_path=None, host=None, power_test=False, is_release_build=False,
+                 debug_mode=False, post_startup_delay=None, activity=None):
+        Raptor.__init__(self, app, binary, run_local, obj_path, gecko_profile,
+                        gecko_profile_interval, gecko_profile_entries, symbols_path,
+                        host, power_test, is_release_build, debug_mode,
+                        post_startup_delay)
 
     def create_browser_handler(self):
         # create the desktop browser runner
         self.log.info("creating browser runner using mozrunner")
         self.output_handler = OutputHandler()
         process_args = {
             'processOutputLine': [self.output_handler],
         }
         runner_cls = runners[self.config['app']]
         self.runner = runner_cls(
             self.config['binary'], profile=self.profile, process_args=process_args,
             symbols_path=self.config['symbols_path'])
 
-    def launch_desktop_browser(self, test):
-        raise NotImplementedError
-
     def start_runner_proc(self):
         # launch the browser via our previously-created runner
         self.runner.start()
         proc = self.runner.process_handler
         self.output_handler.proc = proc
 
         # give our control server the browser process so it can shut it down later
         self.control_server.browser_proc = proc
 
     def run_test(self, test, timeout=None):
         self.run_test_setup(test)
 
+        if test.get('playback', None) is not None:
+            self.start_playback(test)
+
         if self.config['host'] not in ('localhost', '127.0.0.1'):
             self.delete_proxy_settings_from_profile()
 
-        try:
-            # start mitmproxy if requested
-            if test.get('playback') is not None:
-                self.start_playback(test)
-
-            # start the browser/app under test
-            self.launch_desktop_browser(test)
+        # now start the browser/app under test
+        self.launch_desktop_browser(test)
 
-            # set our control server flag to indicate we are running the browser/app
-            self.control_server._finished = False
+        # set our control server flag to indicate we are running the browser/app
+        self.control_server._finished = False
 
-            self.wait_for_test_finish(test, timeout)
+        self.wait_for_test_finish(test, timeout)
 
-        finally:
-            self.run_test_teardown()
+        self.run_test_teardown()
 
-            # browser should be closed by now but this is a backup-shutdown (if not in debug-mode)
-            if not self.debug_mode:
-                if self.runner.is_running():
-                    self.runner.stop()
-            else:
-                # in debug mode, and running locally, leave the browser running
-                if self.config['run_local']:
-                    self.log.info("* debug-mode enabled - please shutdown the browser manually...")
-                    self.runner.wait(timeout=None)
-
-    def run_test_teardown(self):
-        self.log.info("stopping %s" % self.config['app'])
-        self.runner.stop()
-
-        super(RaptorDesktop, self).run_test_teardown()
+        # browser should be closed by now but this is a backup-shutdown (if not in debug-mode)
+        if not self.debug_mode:
+            if self.runner.is_running():
+                self.runner.stop()
+        else:
+            # in debug mode, and running locally, leave the browser running
+            if self.config['run_local']:
+                self.log.info("* debug-mode enabled - please shutdown the browser manually...")
+                self.runner.wait(timeout=None)
 
     def check_for_crashes(self):
         try:
             self.runner.check_for_crashes()
         except NotImplementedError:  # not implemented for Chrome
             pass
 
-    def clean_up(self):
-        self.runner.stop()
-
-        super(RaptorDesktop, self).clean_up()
-
 
 class RaptorDesktopFirefox(RaptorDesktop):
+    def __init__(self, app, binary, run_local=False, obj_path=None,
+                 gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
+                 symbols_path=None, host=None, power_test=False, is_release_build=False,
+                 debug_mode=False, post_startup_delay=None, activity=None):
+        RaptorDesktop.__init__(self, app, binary, run_local, obj_path, gecko_profile,
+                               gecko_profile_interval, gecko_profile_entries, symbols_path,
+                               host, power_test, is_release_build, debug_mode,
+                               post_startup_delay)
 
     def disable_non_local_connections(self):
         # For Firefox we need to set MOZ_DISABLE_NONLOCAL_CONNECTIONS=1 env var before startup
         # when testing release builds from mozilla-beta/release. This is because of restrictions
         # on release builds that require webextensions to be signed unless this env var is set
         self.log.info("setting MOZ_DISABLE_NONLOCAL_CONNECTIONS=1")
         os.environ['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = "1"
 
@@ -460,34 +471,37 @@ class RaptorDesktopFirefox(RaptorDesktop
             self.disable_non_local_connections()
 
         # if running debug-mode, tell Firefox to open the browser console on startup
         if self.debug_mode:
             self.runner.cmdargs.extend(['-jsconsole'])
 
         self.start_runner_proc()
 
-        if self.config['is_release_build'] and test.get('playback') is not None:
+        if self.config['is_release_build'] and test.get('playback', None) is not None:
             self.enable_non_local_connections()
 
         # if geckoProfile is enabled, initialize it
         if self.config['gecko_profile'] is True:
             self._init_gecko_profiling(test)
             # tell the control server the gecko_profile dir; the control server will
             # receive the actual gecko profiles from the web ext and will write them
             # to disk; then profiles are picked up by gecko_profile.symbolicate
             self.control_server.gecko_profile_dir = self.gecko_profiler.gecko_profile_dir
 
-    def set_browser_test_prefs(self, raw_prefs):
-        # add test specific preferences
-        self.log.info("setting test-specific Firefox preferences")
-        self.profile.set_preferences(json.loads(raw_prefs))
-
 
 class RaptorDesktopChrome(RaptorDesktop):
+    def __init__(self, app, binary, run_local=False, obj_path=None,
+                 gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
+                 symbols_path=None, host=None, power_test=False, is_release_build=False,
+                 debug_mode=False, post_startup_delay=None, activity=None):
+        RaptorDesktop.__init__(self, app, binary, run_local, obj_path, gecko_profile,
+                               gecko_profile_interval, gecko_profile_entries, symbols_path,
+                               host, power_test, is_release_build, debug_mode,
+                               post_startup_delay)
 
     def setup_chrome_desktop_for_playback(self):
         # if running a pageload test on google chrome, add the cmd line options
         # to turn on the proxy and ignore security certificate errors
         # if using host localhost, 127.0.0.1.
         chrome_args = [
             '--proxy-server=127.0.0.1:8080',
             '--proxy-bypass-list=localhost;127.0.0.1',
@@ -502,58 +516,35 @@ class RaptorDesktopChrome(RaptorDesktop)
         self.log.info("starting %s" % self.config['app'])
         # some chromium-specfic cmd line opts required
         self.runner.cmdargs.extend(['--use-mock-keychain', '--no-default-browser-check'])
 
         # if running in debug-mode, open the devtools on the raptor test tab
         if self.debug_mode:
             self.runner.cmdargs.extend(['--auto-open-devtools-for-tabs'])
 
-        if test.get('playback') is not None:
+        if test.get('playback', None) is not None:
             self.setup_chrome_desktop_for_playback()
 
         self.start_runner_proc()
 
 
 class RaptorAndroid(Raptor):
-    def __init__(self, app, binary, activity=None, **kwargs):
-        super(RaptorAndroid, self).__init__(app, binary, **kwargs)
+    def __init__(self, app, binary, run_local=False, obj_path=None,
+                 gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
+                 symbols_path=None, host=None, power_test=False, is_release_build=False,
+                 debug_mode=False, post_startup_delay=None, activity=None):
+        Raptor.__init__(self, app, binary, run_local, obj_path, gecko_profile,
+                        gecko_profile_interval, gecko_profile_entries, symbols_path, host,
+                        power_test, is_release_build, debug_mode, post_startup_delay)
 
         # on android, when creating the browser profile, we want to use a 'firefox' type profile
         self.profile_class = "firefox"
         self.config['activity'] = activity
 
-    def set_reverse_port(self, port):
-        tcp_port = "tcp:{}".format(port)
-        self.device.create_socket_connection('reverse', tcp_port, tcp_port)
-
-    def serve_benchmark_source(self, *args, **kwargs):
-        super(RaptorAndroid, self).serve_benchmark_source(*args, **kwargs)
-
-        # for Android we must make the benchmarks server available to the device
-        if self.config['host'] in ('localhost', '127.0.0.1'):
-            self.log.info("making the raptor benchmarks server port available to device")
-            self.set_reverse_port(self.benchmark_port)
-
-    def start_control_server(self):
-        super(RaptorAndroid, self).start_control_server()
-
-        # for Android we must make the control server available to the device
-        if self.config['host'] in ('localhost', '127.0.0.1'):
-            self.log.info("making the raptor control server port available to device")
-            self.set_reverse_port(self.control_server.port)
-
-    def start_playback(self, test):
-        super(RaptorAndroid, self).start_playback(test)
-
-        # for Android we must make the playback server available to the device
-        if self.config['host'] in ('localhost', '127.0.0.1'):
-            self.log.info("making the raptor playback server port available to device")
-            self.set_reverse_port(8080)
-
     def create_browser_handler(self):
         # create the android device handler; it gets initiated and sets up adb etc
         self.log.info("creating android device handler using mozdevice")
         self.device = ADBDevice(verbose=True)
         self.device.clear_logcat()
         self.clear_app_data()
 
     def clear_app_data(self):
@@ -648,30 +639,20 @@ class RaptorAndroid(Raptor):
                 self.log.info("copying %s to %s" % (_source, _dest))
                 shutil.copyfile(_source, _dest)
             else:
                 self.log.critical("unable to find ssl cert db file: %s" % _source)
 
     def run_test(self, test, timeout=None):
         # tests will be run warm (i.e. NO browser restart between page-cycles)
         # unless otheriwse specified in the test INI by using 'cold = true'
-        try:
-            if test.get('cold', False) is True:
-                self.run_test_cold(test, timeout)
-            else:
-                self.run_test_warm(test, timeout)
-
-        except SignalHandlerException:
-            self.device.stop_application(self.config['binary'])
-
-        finally:
-            if self.config['power_test']:
-                finish_android_power_test(self, test['name'])
-
-            self.run_test_teardown()
+        if test.get('cold', False) is True:
+            self.run_test_cold(test, timeout)
+        else:
+            self.run_test_warm(test, timeout)
 
     def run_test_cold(self, test, timeout=None):
         '''
         Run the Raptor test but restart the entire browser app between page-cycles.
 
         Note: For page-load tests, playback will only be started once - at the beginning of all
         browser cycles, and then stopped after all cycles are finished. The proxy is set via prefs
         in the browser profile so those will need to be set again in each new profile/cycle.
@@ -703,17 +684,17 @@ class RaptorAndroid(Raptor):
             self.log.info("begin browser cycle %d of %d for test %s"
                           % (test['browser_cycle'], test['expected_browser_cycles'], test['name']))
 
             self.run_test_setup(test)
 
             if test['browser_cycle'] == 1:
                 self.create_raptor_sdcard_folder()
 
-                if test.get('playback') is not None:
+                if test.get('playback', None) is not None:
                     self.start_playback(test)
 
                     # an ssl cert db has now been created in the profile; copy it out so we
                     # can use the same cert db in future test cycles / browser restarts
                     local_cert_db_dir = tempfile.mkdtemp()
                     self.log.info("backing up browser ssl cert db that was created via certutil")
                     self.copy_cert_db(self.config['local_profile_dir'], local_cert_db_dir)
 
@@ -733,17 +714,17 @@ class RaptorAndroid(Raptor):
 
                 # get cert db from previous cycle profile and copy into new clean profile
                 # this saves us from having to start playback again / recreate cert db etc.
                 self.log.info("copying existing ssl cert db into new browser profile")
                 self.copy_cert_db(local_cert_db_dir, self.config['local_profile_dir'])
 
                 self.run_test_setup(test)
 
-            if test.get('playback') is not None:
+            if test.get('playback', None) is not None:
                 self.turn_on_android_app_proxy()
 
             self.copy_profile_onto_device()
 
             # now start the browser/app under test
             self.launch_firefox_android_app(test['name'])
 
             # set our control server flag to indicate we are running the browser/app
@@ -751,58 +732,59 @@ class RaptorAndroid(Raptor):
 
             self.wait_for_test_finish(test, timeout)
 
             # in debug mode, and running locally, leave the browser running
             if self.debug_mode and self.config['run_local']:
                 self.log.info("* debug-mode enabled - please shutdown the browser manually...")
                 self.runner.wait(timeout=None)
 
+        if self.config['power_test']:
+            finish_android_power_test(self, test['name'])
+
+        self.run_test_teardown()
+
     def run_test_warm(self, test, timeout=None):
         self.log.info("test %s is running in warm mode; browser will NOT be restarted between "
                       "page cycles" % test['name'])
         if self.config['power_test']:
             init_android_power_test(self)
 
         self.run_test_setup(test)
         self.create_raptor_sdcard_folder()
 
-        if test.get('playback') is not None:
+        if test.get('playback', None) is not None:
             self.start_playback(test)
 
         if self.config['host'] not in ('localhost', '127.0.0.1'):
             self.delete_proxy_settings_from_profile()
 
-        if test.get('playback') is not None:
+        if test.get('playback', None) is not None:
             self.turn_on_android_app_proxy()
 
         self.copy_profile_onto_device()
 
         # now start the browser/app under test
         self.launch_firefox_android_app(test['name'])
 
         # set our control server flag to indicate we are running the browser/app
         self.control_server._finished = False
 
         self.wait_for_test_finish(test, timeout)
 
+        if self.config['power_test']:
+            finish_android_power_test(self, test['name'])
+
+        self.run_test_teardown()
+
         # in debug mode, and running locally, leave the browser running
         if self.debug_mode and self.config['run_local']:
             self.log.info("* debug-mode enabled - please shutdown the browser manually...")
             self.runner.wait(timeout=None)
 
-    def run_test_teardown(self):
-        self.log.info('removing reverse socket connections')
-        self.device.remove_socket_connections('reverse')
-
-        self.log.info("stopping %s" % self.config['app'])
-        self.device.stop_application(self.config['binary'])
-
-        super(RaptorAndroid, self).run_test_teardown()
-
     def check_for_crashes(self):
         # Turn off verbose to prevent logcat from being inserted into the main log.
         verbose = self.device._verbose
         self.device._verbose = False
         logcat = self.device.get_logcat()
         self.device._verbose = verbose
         if logcat:
             if mozcrash.check_for_java_exception(logcat, "raptor"):
@@ -816,22 +798,16 @@ class RaptorAndroid(Raptor):
             self.device.pull(remote_dir, dump_dir)
             mozcrash.log_crashes(self.log, dump_dir, self.config['symbols_path'])
         finally:
             try:
                 shutil.rmtree(dump_dir)
             except Exception:
                 self.log.warning("unable to remove directory: %s" % dump_dir)
 
-    def clean_up(self):
-        self.log.info('removing reverse socket connections')
-        self.device.remove_socket_connections('reverse')
-
-        super(RaptorAndroid, self).clean_up()
-
 
 def main(args=sys.argv[1:]):
     args = parse_args()
     commandline.setup_logging('raptor', args, {'tbpl': sys.stdout})
     LOG = get_default_logger(component='raptor-main')
 
     LOG.info("raptor-start")
 
@@ -869,32 +845,27 @@ def main(args=sys.argv[1:]):
                           gecko_profile_interval=args.gecko_profile_interval,
                           gecko_profile_entries=args.gecko_profile_entries,
                           symbols_path=args.symbols_path,
                           host=args.host,
                           power_test=args.power_test,
                           is_release_build=args.is_release_build,
                           debug_mode=args.debug_mode,
                           post_startup_delay=args.post_startup_delay,
-                          activity=args.activity,
-                          interrupt_handler=SignalHandler(),
-                          )
+                          activity=args.activity)
 
     raptor.create_browser_profile()
     raptor.create_browser_handler()
     raptor.start_control_server()
 
-    try:
-        for next_test in raptor_test_list:
-            raptor.run_test(next_test, timeout=int(next_test['page_timeout']))
+    for next_test in raptor_test_list:
+        raptor.run_test(next_test, timeout=int(next_test['page_timeout']))
 
-        success = raptor.process_results(raptor_test_names)
-
-    finally:
-        raptor.clean_up()
+    success = raptor.process_results(raptor_test_names)
+    raptor.clean_up()
 
     if not success:
         # didn't get test results; test timed out or crashed, etc. we want job to fail
         LOG.critical("TEST-UNEXPECTED-FAIL: no raptor test results were found for %s" %
                      ', '.join(raptor_test_names))
         os.sys.exit(1)
 
     # if we have results but one test page timed out (i.e. one tp6 test page didn't load