def testParse(self):
   self.assertTrue(tir_module.IsTimelineInteractionRecord(
       'Interaction.Foo'))
   self.assertTrue(tir_module.IsTimelineInteractionRecord(
       'Interaction.Foo/Bar'))
   self.assertFalse(tir_module.IsTimelineInteractionRecord(
       'SomethingRandom'))
Example #2
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]
Example #3
0
    def testIssuingInteractionRecord(self):
        action_runner = action_runner_module.ActionRunner(self._tab)
        self.Navigate('interaction_enabled_page.html')
        action_runner.Wait(1)
        self._browser.StartTracing(tracing_backend.DEFAULT_TRACE_CATEGORIES)
        interaction = action_runner.BeginInteraction('TestInteraction',
                                                     is_smooth=True)
        interaction.End()
        trace_data = self._browser.StopTracing()
        timeline_model = model.TimelineModel(trace_data)

        records = []
        renderer_thread = timeline_model.GetRendererThreadFromTabId(
            self._tab.id)
        for event in renderer_thread.async_slices:
            if not tir_module.IsTimelineInteractionRecord(event.name):
                continue
            records.append(
                tir_module.TimelineInteractionRecord.FromAsyncEvent(event))
        self.assertEqual(
            1, len(records),
            'Fail to issue the interaction record on tracing timeline.'
            ' Trace data:\n%s' % repr(trace_data.EventData()))
        self.assertEqual('TestInteraction', records[0].logical_name)
        self.assertTrue(records[0].is_smooth)
  def Stop(self, tab):
    # End the smooth marker for all actions.
    runner = action_runner.ActionRunner(None, tab)
    runner.EndInteraction(RUN_SMOOTH_ACTIONS, [tir_module.IS_SMOOTH])
    # Stop tracing.
    timeline_data = tab.browser.StopTracing()
    self._model = TimelineModel(timeline_data)
    self._renderer_process = self._model.GetRendererProcessFromTab(tab)
    renderer_thread = self.model.GetRendererThreadFromTab(tab)

    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.FromEvent(event)
      if r.logical_name == 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
      elif r.is_smooth:
        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]
 def FindTimelineInteractionRecords(self):
     # TODO(nduca): Add support for page-load interaction record.
     return [
         tir_module.TimelineInteractionRecord.FromEvent(event)
         for event in self._renderer_thread.async_slices
         if tir_module.IsTimelineInteractionRecord(event.name)
     ]
 def GetInteractionRecords(self, trace_data):
     timeline_model = model.TimelineModel(trace_data)
     renderer_thread = timeline_model.GetFirstRendererThread(self._tab.id)
     return [
         tir_module.TimelineInteractionRecord.FromAsyncEvent(e)
         for e in renderer_thread.async_slices
         if tir_module.IsTimelineInteractionRecord(e.name)
     ]
    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.')
Example #8
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
    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.

        renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
            tab.id)
        run_smooth_actions_record = None
        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.logical_name == RUN_SMOOTH_ACTIONS:
                assert run_smooth_actions_record is None, (
                    'SmoothnessController cannot issue more than 1 %s record' %
                    RUN_SMOOTH_ACTIONS)
                run_smooth_actions_record = r
            elif r.is_smooth:
                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:
            if run_smooth_actions_record is None:
                sys.stderr.write('Raw tracing data:\n')
                sys.stderr.write(repr(self._tracing_timeline_data.EventData()))
                sys.stderr.write('\n')
                raise Exception(
                    'SmoothnessController failed to issue markers for the '
                    'whole interaction.')
            else:
                smooth_records = [run_smooth_actions_record]

        # Create an interaction_record for this legacy measurement. Since we don't
        # wrap the results that is sent to smoothnes metric, the logical_name will
        # not be used.
        smoothness_metric = smoothness.SmoothnessMetric()
        smoothness_metric.AddResults(self._timeline_model, renderer_thread,
                                     smooth_records, results)
        if tab.browser.platform.IsRawDisplayFrameRateSupported():
            for r in tab.browser.platform.GetRawDisplayFrameRateMeasurements():
                if r.value is None:
                    raise MissingDisplayFrameRateError(r.name)
                results.Add(r.name, r.unit, r.value)
    def testSmoothGestureAdjusted(self):
        ps = self.CreateEmptyPageSet()
        ps.AddUserStory(
            ScrollingPage('file://scrollable_page.html',
                          ps,
                          base_dir=ps.base_dir))
        models = []
        tab_ids = []

        class ScrollingGestureTestMeasurement(page_test.PageTest):
            def __init__(self):
                # pylint: disable=bad-super-call
                super(ScrollingGestureTestMeasurement,
                      self).__init__('RunPageInteractions', False)

            def WillRunActions(self, _page, tab):
                options = tracing_options.TracingOptions()
                options.enable_chrome_trace = True
                tab.browser.platform.tracing_controller.Start(
                    options, tracing_category_filter.TracingCategoryFilter())

            def DidRunActions(self, _page, tab):
                models.append(
                    model_module.TimelineModel(
                        tab.browser.platform.tracing_controller.Stop()))
                tab_ids.append(tab.id)

            def ValidateAndMeasurePage(self, _page, _tab, _results):
                pass

        self.RunMeasurement(ScrollingGestureTestMeasurement(), ps)
        timeline_model = models[0]
        renderer_thread = timeline_model.GetRendererThreadFromTabId(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)
Example #11
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)
Example #12
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)
def _GetRendererThreadsToInteractionRecordsMap(model):
  threads_to_records_map = collections.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)
        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
def _ExtractInteractionsRecordFromThread(thread, timeline_model):
    run_smooth_actions_record = None
    records = []
    for event in thread.async_slices:
        if not tir_module.IsTimelineInteractionRecord(event.name):
            continue
        assert event.start_thread
        assert event.start_thread is event.end_thread
        r = smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
            timeline_model,
            tir_module.TimelineInteractionRecord.FromAsyncEvent(event))
        if r.label == smoothness_controller.RUN_SMOOTH_ACTIONS:
            assert run_smooth_actions_record is None, (
                'There can\'t be more than 1 %s record' %
                smoothness_controller.RUN_SMOOTH_ACTIONS)
            run_smooth_actions_record = r
        else:
            records.append(r)
    if not records:
        # Only include run_smooth_actions_record (label =
        # smoothness_controller.RUN_SMOOTH_ACTIONS) if there is no other records
        records = [run_smooth_actions_record]
    return records
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
  def AddValue(self, value):
    assert self._tir_label
    if value.tir_label:
      assert value.tir_label == self._tir_label
    else:
      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])