Bug 1512983 - Add crash reporting for android raptor; r=rwood
authorGeoff Brown <gbrown@mozilla.com>
Mon, 31 Dec 2018 09:18:00 -0700
changeset 509309 c60891fb93f5ba82e91dc5036b6905f26b3f5d42
parent 509308 6157629ebfa11147618ffc8322d79958229036ca
child 509310 13191d88873d83a81b29cf5a7cc7a5be025faecd
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrwood
bugs1512983
milestone66.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 1512983 - Add crash reporting for android raptor; r=rwood Also fix the symbols path, so that desktop crash reports are symbolicated.
testing/raptor/raptor/raptor.py
--- a/testing/raptor/raptor/raptor.py
+++ b/testing/raptor/raptor/raptor.py
@@ -2,20 +2,24 @@
 
 # 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 subprocess
 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 mozrunner import runners
 
 # need this so raptor imports work both from /raptor and via mach
@@ -126,17 +130,18 @@ class Raptor(object):
             # 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[app]
             self.runner = runner_cls(
-                binary, profile=self.profile, process_args=process_args)
+                binary, profile=self.profile, process_args=process_args,
+                symbols_path=self.config['symbols_path'])
 
         self.log.info("raptor config: %s" % str(self.config))
 
     @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:
@@ -381,24 +386,19 @@ class Raptor(object):
                 if not self.debug_mode:
                     elapsed_time += 1
                     if elapsed_time > (timeout) - 5:  # stop 5 seconds early
                         self.log.info("application timed out after {} seconds".format(timeout))
                         self.control_server.wait_for_quit()
                         break
         finally:
             if self.config['app'] == "geckoview":
-                # TODO: if on geckoview is there some cleanup here i.e. check for crashes?
                 if self.config['power_test']:
                     finish_geckoview_power_test(self)
-            else:
-                try:
-                    self.runner.check_for_crashes()
-                except NotImplementedError:  # not implemented for Chrome
-                    pass
+            self.check_for_crashes()
 
         if self.playback is not None:
             self.playback.stop()
 
         # remove the raptor webext; as it must be reloaded with each subtest anyway
         self.log.info("removing webext %s" % raptor_webext)
         if self.config['app'] in ["firefox", "geckoview"]:
             self.profile.addons.remove_addon(webext_id)
@@ -450,16 +450,41 @@ class Raptor(object):
             raptor_json_path = os.path.join(os.getcwd(), 'local.json')
 
         self.config['raptor_json_path'] = raptor_json_path
         return self.results_handler.summarize_and_output(self.config)
 
     def get_page_timeout_list(self):
         return self.results_handler.page_timeout_list
 
+    def check_for_crashes(self):
+        if self.config['app'] == "geckoview":
+            logcat = self.device.get_logcat()
+            if logcat:
+                if mozcrash.check_for_java_exception(logcat, "raptor"):
+                    return
+            try:
+                dump_dir = tempfile.mkdtemp()
+                remote_dir = posixpath.join(self.device_profile, 'minidumps')
+                if not self.device.is_dir(remote_dir):
+                    self.log.error("No crash directory (%s) found on remote device" % remote_dir)
+                    return
+                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)
+        else:
+            try:
+                self.runner.check_for_crashes()
+            except NotImplementedError:  # not implemented for Chrome
+                pass
+
     def clean_up(self):
         self.control_server.stop()
         if self.config['app'] != "geckoview":
             self.runner.stop()
         elif self.config['app'] == 'geckoview':
             self.log.info('removing reverse socket connections')
             self.device.remove_socket_connections('reverse')
         else: