• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import collections
6import copy
7import traceback
8
9from telemetry import value as value_module
10from telemetry.results import page_run
11from telemetry.results import progress_reporter as progress_reporter_module
12from telemetry.value import failure
13from telemetry.value import skip
14
15
16class PageTestResults(object):
17  def __init__(self, output_stream=None, output_formatters=None,
18               progress_reporter=None, trace_tag=''):
19    """
20    Args:
21      output_stream: The output stream to use to write test results.
22      output_formatters: A list of output formatters. The output
23          formatters are typically used to format the test results, such
24          as CsvOutputFormatter, which output the test results as CSV.
25      progress_reporter: An instance of progress_reporter.ProgressReporter,
26          to be used to output test status/results progressively.
27      trace_tag: A string to append to the buildbot trace
28      name. Currently only used for buildbot.
29    """
30    # TODO(chrishenry): Figure out if trace_tag is still necessary.
31
32    super(PageTestResults, self).__init__()
33    self._output_stream = output_stream
34    self._progress_reporter = (
35        progress_reporter if progress_reporter is not None
36        else progress_reporter_module.ProgressReporter())
37    self._output_formatters = (
38        output_formatters if output_formatters is not None else [])
39    self._trace_tag = trace_tag
40
41    self._current_page_run = None
42    self._all_page_runs = []
43    self._representative_value_for_each_value_name = {}
44    self._all_summary_values = []
45
46  def __copy__(self):
47    cls = self.__class__
48    result = cls.__new__(cls)
49    for k, v in self.__dict__.items():
50      if isinstance(v, collections.Container):
51        v = copy.copy(v)
52      setattr(result, k, v)
53    return result
54
55  @property
56  def all_page_specific_values(self):
57    values = []
58    for run in self._all_page_runs:
59      values += run.values
60    if self._current_page_run:
61      values += self._current_page_run.values
62    return values
63
64  @property
65  def all_summary_values(self):
66    return self._all_summary_values
67
68  @property
69  def current_page(self):
70    assert self._current_page_run, 'Not currently running test.'
71    return self._current_page_run.page
72
73  @property
74  def current_page_run(self):
75    assert self._current_page_run, 'Not currently running test.'
76    return self._current_page_run
77
78  @property
79  def all_page_runs(self):
80    return self._all_page_runs
81
82  @property
83  def pages_that_succeeded(self):
84    """Returns the set of pages that succeeded."""
85    pages = set(run.page for run in self.all_page_runs)
86    pages.difference_update(self.pages_that_failed)
87    return pages
88
89  @property
90  def pages_that_failed(self):
91    """Returns the set of failed pages."""
92    failed_pages = set()
93    for run in self.all_page_runs:
94      if run.failed:
95        failed_pages.add(run.page)
96    return failed_pages
97
98  @property
99  def failures(self):
100    values = self.all_page_specific_values
101    return [v for v in values if isinstance(v, failure.FailureValue)]
102
103  @property
104  def skipped_values(self):
105    values = self.all_page_specific_values
106    return [v for v in values if isinstance(v, skip.SkipValue)]
107
108  def _GetStringFromExcInfo(self, err):
109    return ''.join(traceback.format_exception(*err))
110
111  def WillRunPage(self, page):
112    assert not self._current_page_run, 'Did not call DidRunPage.'
113    self._current_page_run = page_run.PageRun(page)
114    self._progress_reporter.WillRunPage(self)
115
116  def DidRunPage(self, page, discard_run=False):  # pylint: disable=W0613
117    """
118    Args:
119      page: The current page under test.
120      discard_run: Whether to discard the entire run and all of its
121          associated results.
122    """
123    assert self._current_page_run, 'Did not call WillRunPage.'
124    self._progress_reporter.DidRunPage(self)
125    if not discard_run:
126      self._all_page_runs.append(self._current_page_run)
127    self._current_page_run = None
128
129  def WillAttemptPageRun(self, attempt_count, max_attempts):
130    """To be called when a single attempt on a page run is starting.
131
132    This is called between WillRunPage and DidRunPage and can be
133    called multiple times, one for each attempt.
134
135    Args:
136      attempt_count: The current attempt number, start at 1
137          (attempt_count == 1 for the first attempt, 2 for second
138          attempt, and so on).
139      max_attempts: Maximum number of page run attempts before failing.
140    """
141    self._progress_reporter.WillAttemptPageRun(
142        self, attempt_count, max_attempts)
143    # Clear any values from previous attempts for this page run.
144    self._current_page_run.ClearValues()
145
146  def AddValue(self, value):
147    assert self._current_page_run, 'Not currently running test.'
148    self._ValidateValue(value)
149    # TODO(eakuefner/chrishenry): Add only one skip per pagerun assert here
150    self._current_page_run.AddValue(value)
151    self._progress_reporter.DidAddValue(value)
152
153  def AddSummaryValue(self, value):
154    assert value.page is None
155    self._ValidateValue(value)
156    self._all_summary_values.append(value)
157
158  def _ValidateValue(self, value):
159    assert isinstance(value, value_module.Value)
160    if value.name not in self._representative_value_for_each_value_name:
161      self._representative_value_for_each_value_name[value.name] = value
162    representative_value = self._representative_value_for_each_value_name[
163        value.name]
164    assert value.IsMergableWith(representative_value)
165
166  def PrintSummary(self):
167    self._progress_reporter.DidFinishAllTests(self)
168    for output_formatter in self._output_formatters:
169      output_formatter.Format(self)
170
171  def FindPageSpecificValuesForPage(self, page, value_name):
172    values = []
173    for value in self.all_page_specific_values:
174      if value.page == page and value.name == value_name:
175        values.append(value)
176    return values
177
178  def FindAllPageSpecificValuesNamed(self, value_name):
179    values = []
180    for value in self.all_page_specific_values:
181      if value.name == value_name:
182        values.append(value)
183    return values
184