Exemplo n.º 1
0
  def Stop(self, tab, results):
    # End the smooth marker for all actions.
    self._interaction.End()
    # Stop tracing.
    timeline_data = tab.browser.platform.tracing_controller.Stop()
    results.AddValue(trace.TraceValue(
        results.current_page, timeline_data))
    self._model = TimelineModel(timeline_data)
    self._renderer_process = self._model.GetRendererProcessFromTabId(tab.id)
    renderer_thread = self.model.GetRendererThreadFromTabId(tab.id)

    run_smooth_actions_record = None
    self._smooth_records = []
    for event in renderer_thread.async_slices:
      if not tir_module.IsTimelineInteractionRecord(event.name):
        continue
      r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
      if r.label == RUN_SMOOTH_ACTIONS:
        assert run_smooth_actions_record is None, (
          'TimelineController cannot issue more than 1 %s record' %
          RUN_SMOOTH_ACTIONS)
        run_smooth_actions_record = r
      else:
        self._smooth_records.append(
          smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
            self.model, r))

    # If there is no other smooth records, we make measurements on time range
    # marked by timeline_controller itself.
    # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
    # page sets are responsible for issueing the markers themselves.
    if len(self._smooth_records) == 0 and run_smooth_actions_record:
      self._smooth_records = [run_smooth_actions_record]
Exemplo n.º 2
0
    def Stop(self, tab, results):
        # End the smooth marker for all actions.
        if self._enable_auto_issuing_record:
            self._interaction.End()
        # Stop tracing.
        timeline_data = tab.browser.platform.tracing_controller.StopTracing()

        # TODO(charliea): This is part of a three-sided Chromium/Telemetry patch
        # where we're changing the return type of StopTracing from a TraceValue to a
        # (TraceValue, nonfatal_exception_list) tuple. Once the tuple return value
        # lands in Chromium, the non-tuple logic should be deleted.
        if isinstance(timeline_data, tuple):
            timeline_data = timeline_data[0]

        # TODO(#763375): Rely on results.telemetry_info.trace_local_path/etc.
        kwargs = {}
        if hasattr(results.telemetry_info, 'trace_local_path'):
            kwargs['file_path'] = results.telemetry_info.trace_local_path
            kwargs['remote_path'] = results.telemetry_info.trace_remote_path
            kwargs['upload_bucket'] = results.telemetry_info.upload_bucket
            kwargs['cloud_url'] = results.telemetry_info.trace_remote_url
        results.AddValue(
            trace.TraceValue(results.current_page, timeline_data, **kwargs))

        self._model = TimelineModel(timeline_data)
        self._renderer_process = self._model.GetRendererProcessFromTabId(
            tab.id)
        renderer_thread = self.model.GetRendererThreadFromTabId(tab.id)

        run_smooth_actions_record = None
        self._smooth_records = []
        for event in renderer_thread.async_slices:
            if not tir_module.IsTimelineInteractionRecord(event.name):
                continue
            r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
            if r.label == RUN_SMOOTH_ACTIONS:
                assert run_smooth_actions_record is None, (
                    'TimelineController cannot issue more than 1 %s record' %
                    RUN_SMOOTH_ACTIONS)
                run_smooth_actions_record = r
            else:
                self._smooth_records.append(
                    smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
                        self.model, r))

        # If there is no other smooth records, we make measurements on time range
        # marked by timeline_controller itself.
        # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
        # page sets are responsible for issueing the markers themselves.
        if len(self._smooth_records) == 0 and run_smooth_actions_record:
            self._smooth_records = [run_smooth_actions_record]

        if len(self._smooth_records) == 0:
            raise legacy_page_test.Failure(
                'No interaction record was created.')
Exemplo n.º 3
0
def _CollectRecordsFromRendererThreads(model, renderer_thread):
  records = []
  for event in renderer_thread.async_slices:
    if tir_module.IsTimelineInteractionRecord(event.name):
      interaction = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
      # Adjust the interaction record to match the synthetic gesture
      # controller if needed.
      interaction = (
          smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
              model, interaction))
      records.append(interaction)
  return records
Exemplo n.º 4
0
    def testSmoothGestureAdjusted(self):
        ps = self.CreateEmptyPageSet()
        ps.AddStory(
            ScrollingPage('file://scrollable_page.html',
                          ps,
                          base_dir=ps.base_dir))
        models = []
        tab_ids = []

        class ScrollingGestureTestMeasurement(legacy_page_test.LegacyPageTest):
            def __init__(self):
                # pylint: disable=bad-super-call
                super(ScrollingGestureTestMeasurement, self).__init__()

            def WillNavigateToPage(self, page, tab):
                del page  # unused
                config = tracing_config.TracingConfig()
                config.enable_chrome_trace = True
                tab.browser.platform.tracing_controller.StartTracing(config)

            def ValidateAndMeasurePage(self, page, tab, results):
                del page, results  # unused
                models.append(
                    model_module.TimelineModel(
                        tab.browser.platform.tracing_controller.StopTracing()
                        [0]))
                tab_ids.append(tab.id)

        self.RunMeasurement(ScrollingGestureTestMeasurement(), ps)
        timeline_model = models[0]
        renderer_thread = timeline_model.GetFirstRendererThread(tab_ids[0])
        smooth_record = None
        for e in renderer_thread.async_slices:
            if tir_module.IsTimelineInteractionRecord(e.name):
                smooth_record = tir_module.TimelineInteractionRecord.FromAsyncEvent(
                    e)
        self.assertIsNotNone(smooth_record)
        adjusted_smooth_gesture = (
            sg_util.GetAdjustedInteractionIfContainGesture(
                timeline_model, smooth_record))
        # Test that the scroll gesture starts at at least 500ms after the start of
        # the interaction record and ends at at least 500ms before the end of
        # interaction record.
        self.assertLessEqual(
            500, adjusted_smooth_gesture.start - smooth_record.start)
        self.assertLessEqual(500,
                             smooth_record.end - adjusted_smooth_gesture.end)
Exemplo n.º 5
0
    def AddResults(self, tab, results):
        # Add results of smoothness metric. This computes the smoothness metric for
        # the time ranges of gestures, if there is at least one, else the the time
        # ranges from the first action to the last action.
        results.AddValue(
            trace.TraceValue(results.current_page, self._trace_data))
        renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
            tab.id)
        smooth_records = []
        for event in renderer_thread.async_slices:
            if not tir_module.IsTimelineInteractionRecord(event.name):
                continue
            r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
            smooth_records.append(
                smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
                    self._timeline_model, r))

        # If there is no other smooth records, we make measurements on time range
        # marked smoothness_controller itself.
        # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
        # page sets are responsible for issueing the markers themselves.
        if len(smooth_records) == 0:
            raise page_test.Failure('Page failed to issue any markers.')

        # Check to make sure all smooth records have same label and repeatable if
        # there are more than one.
        need_repeatable_flag = len(smooth_records) > 1
        record_label = smooth_records[0].label
        for r in smooth_records:
            if r.label != record_label:
                raise page_test.Failure(
                    'SmoothController does not support multiple interactions with '
                    'different label. Interactions: %s' % repr(smooth_records))
            if need_repeatable_flag and not r.repeatable:
                raise page_test.Failure(
                    'If there are more than one interaction record, each interaction '
                    'must has repeatable flag. Interactions: %s' %
                    repr(smooth_records))

        # Create an interaction_record for this legacy measurement. Since we don't
        # wrap the results that are sent to smoothness metric, the label will
        # not be used.
        smoothness_metric = smoothness.SmoothnessMetric()
        smoothness_metric.AddResults(self._timeline_model, renderer_thread,
                                     smooth_records, results)
Exemplo n.º 6
0
def _GetRendererThreadsToInteractionRecordsMap(model):
  threads_to_records_map = defaultdict(list)
  interaction_labels_of_previous_threads = set()
  for curr_thread in model.GetAllThreads():
    for event in curr_thread.async_slices:
      # TODO(nduca): Add support for page-load interaction record.
      if tir_module.IsTimelineInteractionRecord(event.name):
        interaction = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
        # Adjust the interaction record to match the synthetic gesture
        # controller if needed.
        interaction = (
            smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
                model, interaction))
        threads_to_records_map[curr_thread].append(interaction)
        if interaction.label in interaction_labels_of_previous_threads:
          raise InvalidInteractions(
            'Interaction record label %s is duplicated on different '
            'threads' % interaction.label)
    if curr_thread in threads_to_records_map:
      interaction_labels_of_previous_threads.update(
        r.label for r in threads_to_records_map[curr_thread])

  return threads_to_records_map
Exemplo n.º 7
0
    def testGetAdjustedInteractionIfContainGesture(self):
        model = model_module.TimelineModel()
        renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
        renderer_main.name = 'CrRendererMain'

        #      [          X          ]                   [   Y  ]
        #      [  sub_async_slice_X  ]
        #          [   record_1]
        #          [   record_6]
        #  [  record_2 ]          [ record_3 ]
        #  [           record_4              ]
        #                                [ record_5 ]
        #
        # Note: X and Y are async slice with name
        # SyntheticGestureController::running

        async_slice_X = async_slice.AsyncSlice(
            'X',
            'SyntheticGestureController::running',
            10,
            duration=20,
            start_thread=renderer_main,
            end_thread=renderer_main)

        sub_async_slice_X = async_slice.AsyncSlice(
            'X',
            'SyntheticGestureController::running',
            10,
            duration=20,
            start_thread=renderer_main,
            end_thread=renderer_main)
        sub_async_slice_X.parent_slice = async_slice_X
        async_slice_X.AddSubSlice(sub_async_slice_X)

        async_slice_Y = async_slice.AsyncSlice(
            'X',
            'SyntheticGestureController::running',
            60,
            duration=20,
            start_thread=renderer_main,
            end_thread=renderer_main)

        renderer_main.AddAsyncSlice(async_slice_X)
        renderer_main.AddAsyncSlice(async_slice_Y)

        model.FinalizeImport(shift_world_to_zero=False)

        record_1 = tir_module.TimelineInteractionRecord(
            'Gesture_included', 15, 25)
        record_2 = tir_module.TimelineInteractionRecord(
            'Gesture_overlapped_left', 5, 25)
        record_3 = tir_module.TimelineInteractionRecord(
            'Gesture_overlapped_right', 25, 35)
        record_4 = tir_module.TimelineInteractionRecord(
            'Gesture_containing', 5, 35)
        record_5 = tir_module.TimelineInteractionRecord(
            'Gesture_non_overlapped', 35, 45)
        record_6 = tir_module.TimelineInteractionRecord(
            'Action_included', 15, 25)

        adjusted_record_1 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_1)
        self.assertEquals(adjusted_record_1.start, 10)
        self.assertEquals(adjusted_record_1.end, 30)
        self.assertTrue(adjusted_record_1 is not record_1)

        adjusted_record_2 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_2)
        self.assertEquals(adjusted_record_2.start, 10)
        self.assertEquals(adjusted_record_2.end, 30)

        adjusted_record_3 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_3)
        self.assertEquals(adjusted_record_3.start, 10)
        self.assertEquals(adjusted_record_3.end, 30)

        adjusted_record_4 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_4)
        self.assertEquals(adjusted_record_4.start, 10)
        self.assertEquals(adjusted_record_4.end, 30)

        adjusted_record_5 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_5)
        self.assertEquals(adjusted_record_5.start, 35)
        self.assertEquals(adjusted_record_5.end, 45)
        self.assertTrue(adjusted_record_5 is not record_5)

        adjusted_record_6 = sg_util.GetAdjustedInteractionIfContainGesture(
            model, record_6)
        self.assertEquals(adjusted_record_6.start, 15)
        self.assertEquals(adjusted_record_6.end, 25)
        self.assertTrue(adjusted_record_6 is not record_6)
      value.tir_label = self._tir_label
    self._results.AddValue(value)


def _GetRendererThreadsToInteractionRecordsMap(domain.model):
  threads_to_records_map = defaultdict(list)
  interaction_labels_of_previous_threads = set()
  for curr_thread in domain.model.GetAllThreads():
    for event in curr_thread.async_slices:
      # TODO(nduca): Add support for page-load interaction record.
      if tir_module.IsTimelineInteractionRecord(event.name):
        interaction = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
        # Adjust the interaction record to match the synthetic gesture
        # controller if needed.
        interaction = (
            smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
                domain.model, interaction))
        threads_to_records_map[curr_thread].append(interaction)
        if interaction.label in interaction_labels_of_previous_threads:
          raise InvalidInteractions(
            'Interaction record label %s is duplicated on different '
            'threads' % interaction.label)
    if curr_thread in threads_to_records_map:
      interaction_labels_of_previous_threads.update(
        r.label for r in threads_to_records_map[curr_thread])

  return threads_to_records_map


class _TimelineBasedMetrics(object):
  def __init__(self, domain.model, renderer_thread, interaction_records,
               results_wrapper, metrics):