diff options
Diffstat (limited to 'testing/marionette/harness/marionette_harness/tests/unit/test_crash.py')
-rw-r--r-- | testing/marionette/harness/marionette_harness/tests/unit/test_crash.py | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_crash.py b/testing/marionette/harness/marionette_harness/tests/unit/test_crash.py new file mode 100644 index 000000000..7e74f0857 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_crash.py @@ -0,0 +1,155 @@ +# 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 glob +import shutil + +from marionette_driver.errors import MarionetteException +# Import runner module to monkey patch mozcrash module +from mozrunner.base import runner + +from marionette_harness import MarionetteTestCase, expectedFailure, run_if_e10s + + +class MockMozCrash(object): + """Mock object to replace original mozcrash methods.""" + + def __init__(self, marionette): + self.marionette = marionette + + with self.marionette.using_context('chrome'): + self.crash_reporter_enabled = self.marionette.execute_script(""" + try { + Components.classes["@mozilla.org/toolkit/crash-reporter;1"]. + getService(Components.interfaces.nsICrashReporter); + return true; + } catch (exc) { + return false; + } + """) + + def check_for_crashes(self, dump_directory, *args, **kwargs): + minidump_files = glob.glob('{}/*.dmp'.format(dump_directory)) + shutil.rmtree(dump_directory, ignore_errors=True) + + if self.crash_reporter_enabled: + return len(minidump_files) + else: + return len(minidump_files) == 0 + + def log_crashes(self, logger, dump_directory, *args, **kwargs): + return self.check_for_crashes(dump_directory, *args, **kwargs) + + +class BaseCrashTestCase(MarionetteTestCase): + + # Reduce the timeout for faster processing of the tests + socket_timeout = 10 + + def setUp(self): + super(BaseCrashTestCase, self).setUp() + + self.mozcrash_mock = MockMozCrash(self.marionette) + self.crash_count = self.marionette.crashed + self.pid = self.marionette.process_id + self.remote_uri = self.marionette.absolute_url("javascriptPage.html") + + def tearDown(self): + self.marionette.crashed = self.crash_count + + super(BaseCrashTestCase, self).tearDown() + + def crash(self, chrome=True): + context = 'chrome' if chrome else 'content' + sandbox = None if chrome else 'system' + + # Monkey patch mozcrash to avoid crash info output only for our triggered crashes. + mozcrash = runner.mozcrash + runner.mozcrash = self.mozcrash_mock + + socket_timeout = self.marionette.client.socket_timeout + + self.marionette.set_context(context) + try: + self.marionette.client.socket_timeout = self.socket_timeout + self.marionette.execute_script(""" + // Copied from crash me simple + Components.utils.import("resource://gre/modules/ctypes.jsm"); + + // ctypes checks for NULL pointer derefs, so just go near-NULL. + var zero = new ctypes.intptr_t(8); + var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); + var crash = badptr.contents; + """, sandbox=sandbox) + finally: + runner.mozcrash = mozcrash + self.marionette.client.socket_timeout = socket_timeout + + +class TestCrash(BaseCrashTestCase): + + def test_crash_chrome_process(self): + self.assertRaisesRegexp(IOError, 'Process crashed', + self.crash, chrome=True) + self.assertEqual(self.marionette.crashed, 1) + self.assertIsNone(self.marionette.session) + self.assertRaisesRegexp(MarionetteException, 'Please start a session', + self.marionette.get_url) + + self.marionette.start_session() + self.assertNotEqual(self.marionette.process_id, self.pid) + + # TODO: Bug 1314594 - Causes a hang for the communication between the + # chrome and frame script. + # self.marionette.get_url() + + @run_if_e10s("Content crashes only exist in e10s mode") + def test_crash_content_process(self): + # If e10s is disabled the chrome process crashes + self.marionette.navigate(self.remote_uri) + + self.assertRaisesRegexp(IOError, 'Content process crashed', + self.crash, chrome=False) + self.assertEqual(self.marionette.crashed, 1) + self.assertIsNone(self.marionette.session) + self.assertRaisesRegexp(MarionetteException, 'Please start a session', + self.marionette.get_url) + + self.marionette.start_session() + self.assertNotEqual(self.marionette.process_id, self.pid) + self.marionette.get_url() + + @expectedFailure + def test_unexpected_crash(self): + self.crash(chrome=True) + + +class TestCrashInSetUp(BaseCrashTestCase): + + def setUp(self): + super(TestCrashInSetUp, self).setUp() + + self.assertRaisesRegexp(IOError, 'Process crashed', + self.crash, chrome=True) + self.assertEqual(self.marionette.crashed, 1) + self.assertIsNone(self.marionette.session) + + def test_crash_in_setup(self): + self.marionette.start_session() + self.assertNotEqual(self.marionette.process_id, self.pid) + + +class TestCrashInTearDown(BaseCrashTestCase): + + def tearDown(self): + try: + self.assertRaisesRegexp(IOError, 'Process crashed', + self.crash, chrome=True) + finally: + self.assertEqual(self.marionette.crashed, 1) + self.assertIsNone(self.marionette.session) + super(TestCrashInTearDown, self).tearDown() + + def test_crash_in_teardown(self): + pass |