예제 #1
0
    def pid(self):
        try:
            # Although there might be multiple processes sharing the same name as
            # the browser app, the browser process is the only one being a direct
            # descendant of an Android zygote. (See crbug.com/785446)
            zygotes = self.device.ListProcesses('zygote')
            zygote_pids = set(p.pid for p in zygotes)
            assert zygote_pids, 'No Android zygote found'

            processes = self.device.ListProcesses(
                self._backend_settings.package)
            pids = []
            for process in processes:
                if (process.name == self._backend_settings.package
                        and process.ppid in zygote_pids):
                    pids.append(process.pid)
            assert len(pids) <= 1, 'Found too many browsers: %r' % pids
        except Exception as exc:
            # Re-raise as an AppCrashException to get further diagnostic information.
            # In particular we also get the values of all local variables above.
            raise exceptions.AppCrashException(
                self.browser, 'Error getting browser PID: %s' % exc)
        if not pids:
            raise exceptions.BrowserGoneException(self.browser)
        return pids[0]
예제 #2
0
 def testReturnCodeCaughtException(self):
   fake_benchmark = FakeBenchmark(stories=[
       test_stories.DummyStory(
           'story', run_side_effect=exceptions.AppCrashException())])
   options = self.GetFakeBrowserOptions()
   return_code = story_runner.RunBenchmark(fake_benchmark, options)
   self.assertEqual(return_code, exit_codes.TEST_FAILURE)
예제 #3
0
    def testRunStoryAndProcessErrorIfNeeded_tryAppCrash(self):
        tmp = tempfile.NamedTemporaryFile(delete=False)
        tmp.close()
        temp_file_path = tmp.name
        fake_app = fakes.FakeApp()
        fake_app.recent_minidump_path = temp_file_path
        try:
            app_crash_exception = exceptions.AppCrashException(fake_app,
                                                               msg='foo')
            root_mock = self._CreateErrorProcessingMock(
                method_exceptions={'state.WillRunStory': app_crash_exception})

            with self.assertRaises(exceptions.AppCrashException):
                story_runner._RunStoryAndProcessErrorIfNeeded(
                    root_mock.story, root_mock.results, root_mock.state,
                    root_mock.test, self.finder_options)

            self.assertListEqual(root_mock.method_calls, [
                mock.call.results.CreateArtifact('logs.txt'),
                mock.call.test.WillRunStory(root_mock.state.platform,
                                            root_mock.story),
                mock.call.state.WillRunStory(root_mock.story),
                mock.call.state.DumpStateUponStoryRunFailure(
                    root_mock.results),
                mock.call.results.Fail(
                    'Exception raised running %s' % root_mock.story.name),
                mock.call.test.DidRunStory(root_mock.state.platform,
                                           root_mock.results),
                mock.call.state.DidRunStory(root_mock.results),
            ])
        finally:
            os.remove(temp_file_path)
예제 #4
0
  def testAppCrashThenRaiseInTearDown_Interrupted(
      self, tear_down_state, dump_state_upon_story_run_failure):
    class TearDownStateException(Exception):
      pass

    tear_down_state.side_effect = TearDownStateException()
    root_mock = mock.Mock()
    root_mock.attach_mock(tear_down_state, 'state.TearDownState')
    root_mock.attach_mock(dump_state_upon_story_run_failure,
                          'state.DumpStateUponStoryRunFailure')
    self.RunStories([
        test_stories.DummyStory(
            'foo', run_side_effect=exceptions.AppCrashException(msg='crash!')),
        test_stories.DummyStory('bar')])

    self.assertEqual([call[0] for call in root_mock.mock_calls], [
        'state.DumpStateUponStoryRunFailure',
        # This tear down happens because of the app crash.
        'state.TearDownState',
        # This one happens since state must be re-created to check whether
        # later stories should be skipped or unexpectedly skipped. Then
        # state is torn down normally at the end of the runs.
        'state.TearDownState'
    ])

    test_results = self.ReadTestResults()
    self.assertEqual(len(test_results), 2)
    # First story unexpectedly failed with AppCrashException.
    self.assertEqual(test_results[0]['status'], 'FAIL')
    self.assertFalse(test_results[0]['expected'])
    # Second story unexpectedly skipped due to exception during tear down.
    self.assertEqual(test_results[1]['status'], 'SKIP')
    self.assertFalse(test_results[1]['expected'])
예제 #5
0
  def _ConvertExceptionFromInspectorWebsocket(self, error):
    """Converts an Exception from inspector_websocket.

    This method always raises a Telemetry exception. It appends debugging
    information. The exact exception raised depends on |error|.

    Args:
      error: An instance of socket.error or
        inspector_websocket.WebSocketException.
    Raises:
      exceptions.TimeoutException: A timeout occurred.
      exceptions.DevtoolsTargetCrashException: On any other error, the most
        likely explanation is that the devtool's target crashed.
    """
    # pylint: disable=redefined-variable-type
    if isinstance(error, inspector_websocket.WebSocketException):
      new_error = exceptions.TimeoutException()
      new_error.AddDebuggingMessage(exceptions.AppCrashException(
          self.app, 'The app is probably crashed:\n'))
    else:
      new_error = exceptions.DevtoolsTargetCrashException(self.app)

    original_error_msg = 'Original exception:\n' + str(error)
    new_error.AddDebuggingMessage(original_error_msg)
    self._AddDebuggingInformation(new_error)

    raise new_error, None, sys.exc_info()[2]
예제 #6
0
 def testAppCrashExceptionCausesFailure(self):
   self.RunStories([test_stories.DummyStory(
       'story',
       run_side_effect=exceptions.AppCrashException(msg='App Foo crashes'))])
   test_results = self.ReadTestResults()
   self.assertEqual(['FAIL'],
                    [test['status'] for test in test_results])
   self.assertIn('App Foo crashes', sys.stderr.getvalue())
예제 #7
0
 def DumpMemory(self, timeout=None):
     try:
         return self._browser_backend.DumpMemory(timeout=timeout)
     except tracing_backend.TracingUnrecoverableException:
         logging.exception('Failed to record memory dump due to exception:')
         # Re-raise as an AppCrashException to obtain further debug information
         # about the browser state.
         raise exceptions.AppCrashException(
             app=self, msg='Browser failed to record memory dump.')
예제 #8
0
  def testNoScreenShotTakenForFailedPageDueToNoSupport(self):
    # The default "FakePlatform" does not support taking screenshots.
    self.assertFalse(self.fake_platform.CanTakeScreenshot())
    self.options.browser_options.take_screenshot_for_failed_page = True

    story_set = test_stories.SinglePageStorySet(
        story_run_side_effect=exceptions.AppCrashException(msg='fake crash'))
    results = self.RunStorySetAndGetResults(story_set)

    self.assertEqual(results['status'], 'FAIL')
    self.assertNotIn('screenshot.png', results['outputArtifacts'])
예제 #9
0
 def processes(self):
   try:
     zygotes = self.device.ListProcesses('zygote')
     zygote_pids = set(p.pid for p in zygotes)
     assert zygote_pids, 'No Android zygote found'
     processes = self.device.ListProcesses(self._backend_settings.package)
     return [p for p in processes if p.ppid in zygote_pids]
   except Exception as exc:
     # Re-raise as an AppCrashException to get further diagnostic information.
     # In particular we also get the values of all local variables above.
     raise exceptions.AppCrashException(
         self.browser, 'Error getting browser PIDs: %s' % exc)
예제 #10
0
 def pid(self):
     try:
         pid = self.device.GetApplicationPids(
             self._backend_settings.package, at_most_one=True)
     except device_errors.CommandFailedError as exc:
         logging.warning('Dumping output of "ps" command for diagnosis:')
         for line in self.device.RunShellCommand(['ps']):
             logging.warning('- %s', line)
         # This may happen if we end up with two PIDs for the browser process.
         # Re-raise as an AppCrashException to get further debug information.
         raise exceptions.AppCrashException(
             self.browser, 'Error getting browser PID: %s' % exc)
     if not pid:
         raise exceptions.BrowserGoneException(self.browser)
     return int(pid)
예제 #11
0
  def testScreenShotTakenForFailedPageOnSupportedPlatform(self):
    expected_png_base64 = ('iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91'
                           'JpzAAAAFklEQVR4Xg3EAQ0AAABAMP1LY3YI7l8l6A'
                           'T8tgwbJAAAAABJRU5ErkJggg==')
    self.fake_platform.screenshot_png_data = expected_png_base64
    # After setting up some fake data, now the platform supports screenshots.
    self.assertTrue(self.fake_platform.CanTakeScreenshot())
    self.options.browser_options.take_screenshot_for_failed_page = True

    story_set = test_stories.SinglePageStorySet(
        story_run_side_effect=exceptions.AppCrashException(msg='fake crash'))
    results = self.RunStorySetAndGetResults(story_set)

    self.assertEqual(results['status'], 'FAIL')
    self.assertIn('screenshot.png', results['outputArtifacts'])

    actual_screenshot_img = image_util.FromPngFile(
        results['outputArtifacts']['screenshot.png']['filePath'])
    self.assertTrue(
        image_util.AreEqual(
            image_util.FromBase64Png(expected_png_base64),
            actual_screenshot_img))
 def WillRunUserStory(self, user_storyz):
   raise exceptions.AppCrashException('App Foo crashes')
예제 #13
0
 def WillRunStory(self, story):
     raise exceptions.AppCrashException(msg='App Foo crashes')