Bug 1299216 - [mozrunner] check_for_crashes() has to return the crash count since its last invocation. draft
authorHenrik Skupin <mail@hskupin.info>
Wed, 21 Sep 2016 12:57:50 +0200
changeset 435299 af8f3672941d49baf57b60e44aa9de2883cb2ee7
parent 435298 ed40141d081a6fe0bc5a11d33003d0f96d1a590d
child 435300 402d5358602f7a416d8a43fd90f860d34f275afe
push id34992
push userbmo:hskupin@gmail.com
push dateTue, 08 Nov 2016 11:06:47 +0000
bugs1299216
milestone52.0a1
Bug 1299216 - [mozrunner] check_for_crashes() has to return the crash count since its last invocation. Adapt check_for_crashes() for latest mozcrash changes, which returns the number of crashes for both log_crashes() and check_for_crashes() now. Also the runner should accumulate the number of crashes so it will be known at any time how many times the process has been crashed. MozReview-Commit-ID: Dl9FlH1TalH
testing/mozbase/mozrunner/mozrunner/base/runner.py
testing/mozbase/mozrunner/tests/manifest.ini
testing/mozbase/mozrunner/tests/test_crash.py
--- a/testing/mozbase/mozrunner/mozrunner/base/runner.py
+++ b/testing/mozbase/mozrunner/mozrunner/base/runner.py
@@ -36,16 +36,18 @@ class BaseRunner(object):
 
         if isinstance(profile, basestring):
             self.profile = self.app_ctx.profile_class(profile=profile,
                                                       addons=addons)
         else:
             self.profile = profile or self.app_ctx.profile_class(**getattr(self.app_ctx,
                                                                            'profile_args', {}))
 
+        self.logger = get_default_logger()
+
         # process environment
         if env is None:
             self.env = os.environ.copy()
         else:
             self.env = env.copy()
 
         self.clean_profile = clean_profile
         self.process_class = process_class or ProcessHandler
@@ -94,19 +96,18 @@ class BaseRunner(object):
 
         # ensure the runner is stopped
         self.stop()
 
         # attach a debugger, if specified
         if debug_args:
             cmd = list(debug_args) + cmd
 
-        logger = get_default_logger()
-        if logger:
-            logger.info('Application command: %s' % ' '.join(cmd))
+        if self.logger:
+            self.logger.info('Application command: %s' % ' '.join(cmd))
         if interactive:
             self.process_handler = subprocess.Popen(cmd, env=self.env)
             # TODO: other arguments
         else:
             # this run uses the managed processhandler
             self.process_handler = self.process_class(cmd, env=self.env, **self.process_args)
             self.process_handler.run(self.timeout, self.output_timeout)
 
@@ -174,59 +175,59 @@ class BaseRunner(object):
         """
         Reset the runner to its default state.
         """
         self.stop()
         self.process_handler = None
 
     def check_for_crashes(self, dump_directory=None, dump_save_path=None,
                           test_name=None, quiet=False):
-        """
-        Check for a possible crash and output stack trace.
+        """Check for possible crashes and output the stack traces.
 
         :param dump_directory: Directory to search for minidump files
         :param dump_save_path: Directory to save the minidump files to
         :param test_name: Name to use in the crash output
         :param quiet: If `True` don't print the PROCESS-CRASH message to stdout
-        :returns: True if a crash was detected, otherwise False
+
+        :returns: Number of crashes which have been detected since the last invocation
         """
+        crash_count = 0
+
         if not dump_directory:
             dump_directory = os.path.join(self.profile.profile, 'minidumps')
 
         if not dump_save_path:
             dump_save_path = self.dump_save_path
 
+        if not test_name:
+            test_name = "runner.py"
+
         try:
-            logger = get_default_logger()
-            if logger is not None:
-                if test_name is None:
-                    test_name = "runner.py"
+            if self.logger:
                 if mozcrash:
-                    self.crashed += mozcrash.log_crashes(
-                        logger,
+                    crash_count = mozcrash.log_crashes(
+                        self.logger,
                         dump_directory,
                         self.symbols_path,
                         dump_save_path=dump_save_path,
                         test=test_name)
                 else:
-                    logger.warning("Can not log crashes without mozcrash")
+                    self.logger.warning("Can not log crashes without mozcrash")
             else:
                 if mozcrash:
-                    crashed = mozcrash.check_for_crashes(
+                    crash_count = mozcrash.check_for_crashes(
                         dump_directory,
                         self.symbols_path,
                         dump_save_path=dump_save_path,
                         test_name=test_name,
                         quiet=quiet)
-                    if crashed:
-                        self.crashed += 1
-                else:
-                    logger.warning("Can not log crashes without mozcrash")
+
+            self.crashed += crash_count
         except:
             traceback.print_exc()
 
-        return self.crashed
+        return crash_count
 
     def cleanup(self):
         """
         Cleanup all runner state
         """
         self.stop()
--- a/testing/mozbase/mozrunner/tests/manifest.ini
+++ b/testing/mozbase/mozrunner/tests/manifest.ini
@@ -1,6 +1,7 @@
+[test_crash.py]
 [test_interactive.py]
 [test_start.py]
 [test_states.py]
 [test_stop.py]
 [test_threads.py]
 [test_wait.py]
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozrunner/tests/test_crash.py
@@ -0,0 +1,37 @@
+#!/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/.
+
+import mock
+
+import mozrunnertest
+
+
+class MozrunnerCrashTestCase(mozrunnertest.MozrunnerTestCase):
+
+    @mock.patch('mozcrash.log_crashes', return_value=2)
+    def test_crash_count_with_logger(self, log_crashes):
+        self.assertEqual(self.runner.crashed, 0)
+        self.assertEqual(self.runner.check_for_crashes(), 2)
+        self.assertEqual(self.runner.crashed, 2)
+        self.assertEqual(self.runner.check_for_crashes(), 2)
+        self.assertEqual(self.runner.crashed, 4)
+
+        log_crashes.return_value = 0
+        self.assertEqual(self.runner.check_for_crashes(), 0)
+        self.assertEqual(self.runner.crashed, 4)
+
+    @mock.patch('mozcrash.check_for_crashes', return_value=2)
+    def test_crash_count_without_logger(self, check_for_crashes):
+        self.runner.logger = None
+
+        self.assertEqual(self.runner.crashed, 0)
+        self.assertEqual(self.runner.check_for_crashes(), 2)
+        self.assertEqual(self.runner.crashed, 2)
+        self.assertEqual(self.runner.check_for_crashes(), 2)
+        self.assertEqual(self.runner.crashed, 4)
+
+        check_for_crashes.return_value = 0
+        self.assertEqual(self.runner.check_for_crashes(), 0)
+        self.assertEqual(self.runner.crashed, 4)