1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5
6class TimelineBasedMetricException(Exception):
7  """Exception that can be thrown from metrics that implements
8     TimelineBasedMetric to indicate a problem arised when computing the metric.
9     """
10
11
12def _TimeRangesHasOverlap(iterable_time_ranges):
13  """ Returns True if there is are overlapped ranges in time ranges.
14  iterable_time_ranges: an iterable of time ranges. Each time range is a
15  tuple (start time, end time).
16  """
17  # Sort the ranges by the start time
18  sorted_time_ranges = sorted(iterable_time_ranges)
19  last_range = sorted_time_ranges[0]
20  for current_range in sorted_time_ranges[1:]:
21    start_current_range = current_range[0]
22    end_last_range = last_range[1]
23    if start_current_range < end_last_range:
24      return True
25    last_range = current_range
26  return False
27
28
29class TimelineBasedMetric(object):
30
31  def __init__(self):
32    """Computes metrics from a telemetry.timeline Model and a range
33
34    """
35    super(TimelineBasedMetric, self).__init__()
36
37  def AddResults(self, model, renderer_thread, interaction_records, results):
38    """Computes and adds metrics for the interaction_records' time ranges.
39
40    The override of this method should compute results on the data **only**
41    within the interaction_records' start and end time ranges.
42
43    Args:
44      model: An instance of telemetry.timeline.model.TimelineModel.
45      interaction_records: A list of instances of TimelineInteractionRecord. If
46        the override of this method doesn't support overlapped ranges, use
47        VerifyNonOverlappedRecords to check that no records are overlapped.
48      results: An instance of page.PageTestResults.
49
50    """
51    raise NotImplementedError()
52
53  def VerifyNonOverlappedRecords(self, interaction_records):
54    """This raises exceptions if interaction_records contain overlapped ranges.
55    """
56    if _TimeRangesHasOverlap(((r.start, r.end) for r in interaction_records)):
57      raise TimelineBasedMetricException(
58          'This metric does not support interaction records with overlapped '
59          'time range.')
60