summaryrefslogtreecommitdiffstats
path: root/testing/marionette/harness/marionette_harness/tests/unit/test_crash.py
diff options
context:
space:
mode:
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.py155
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