OLD | NEW |
| (Empty) |
1 # Copyright (c) 2010, Google Inc. All rights reserved. | |
2 # | |
3 # Redistribution and use in source and binary forms, with or without | |
4 # modification, are permitted provided that the following conditions are | |
5 # met: | |
6 # | |
7 # * Redistributions of source code must retain the above copyright | |
8 # notice, this list of conditions and the following disclaimer. | |
9 # * Redistributions in binary form must reproduce the above | |
10 # copyright notice, this list of conditions and the following disclaimer | |
11 # in the documentation and/or other materials provided with the | |
12 # distribution. | |
13 # * Neither the name of Google Inc. nor the names of its | |
14 # contributors may be used to endorse or promote products derived from | |
15 # this software without specific prior written permission. | |
16 # | |
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | |
29 import json | |
30 | |
31 from webkitpy.common.memoized import memoized | |
32 from webkitpy.layout_tests.layout_package import json_results_generator | |
33 | |
34 | |
35 class LayoutTestResult(object): | |
36 | |
37 def __init__(self, test_name, result_dict): | |
38 self._test_name = test_name | |
39 self._result_dict = result_dict | |
40 | |
41 def result_dict(self): | |
42 return self._result_dict | |
43 | |
44 def test_name(self): | |
45 return self._test_name | |
46 | |
47 def did_pass_or_run_as_expected(self): | |
48 return self.did_pass() or self.did_run_as_expected() | |
49 | |
50 def did_pass(self): | |
51 return 'PASS' in self.actual_results() | |
52 | |
53 def did_run_as_expected(self): | |
54 return not self._result_dict.get('is_unexpected', False) | |
55 | |
56 def is_missing_image(self): | |
57 return self._result_dict.get('is_missing_image', False) | |
58 | |
59 def is_missing_text(self): | |
60 return self._result_dict.get('is_missing_text', False) | |
61 | |
62 def is_missing_audio(self): | |
63 return self._result_dict.get('is_missing_audio', False) | |
64 | |
65 def actual_results(self): | |
66 return self._result_dict['actual'] | |
67 | |
68 def expected_results(self): | |
69 return self._result_dict['expected'] | |
70 | |
71 def has_mismatch_result(self): | |
72 last_retry_result = self.actual_results().split()[-1] | |
73 return last_retry_result in ('TEXT', 'IMAGE', 'IMAGE+TEXT', 'AUDIO') | |
74 | |
75 def is_missing_baseline(self): | |
76 return self._result_dict['actual'] == 'MISSING' | |
77 | |
78 | |
79 # FIXME: This should be unified with ResultsSummary or other NRWT layout tests c
ode | |
80 # in the layout_tests package. | |
81 # This doesn't belong in common.net, but we don't have a better place for it yet
. | |
82 class LayoutTestResults(object): | |
83 | |
84 @classmethod | |
85 def results_from_string(cls, string, chromium_revision=None): | |
86 """Creates a LayoutTestResults object from a test result JSON string. | |
87 | |
88 Args: | |
89 string: JSON string containing layout test result. | |
90 chromium_revision: If given, it will override the chromium_revision | |
91 field in json, to indicate the last revision that has completed | |
92 uploading onto the storage server. chromium_revision can be a | |
93 git hash or position number. | |
94 """ | |
95 | |
96 if not string: | |
97 return None | |
98 | |
99 content_string = json_results_generator.strip_json_wrapper(string) | |
100 json_dict = json.loads(content_string) | |
101 if not json_dict: | |
102 return None | |
103 | |
104 return cls(json_dict, chromium_revision) | |
105 | |
106 def __init__(self, parsed_json, chromium_revision=None): | |
107 self._results = parsed_json | |
108 self._chromium_revision = chromium_revision | |
109 | |
110 def run_was_interrupted(self): | |
111 return self._results["interrupted"] | |
112 | |
113 def builder_name(self): | |
114 return self._results["builder_name"] | |
115 | |
116 @memoized | |
117 def chromium_revision(self, scm=None): | |
118 """Returns the revision of the results in commit position number format.
""" | |
119 revision = self._chromium_revision or self._results["chromium_revision"] | |
120 if not revision.isdigit(): | |
121 assert scm, "scm is required if the original revision is a git hash.
" | |
122 revision = scm.commit_position_from_git_commit(revision) | |
123 return int(revision) | |
124 | |
125 def result_for_test(self, test): | |
126 parts = test.split("/") | |
127 tree = self._test_result_tree() | |
128 for part in parts: | |
129 if part not in tree: | |
130 return None | |
131 tree = tree[part] | |
132 return LayoutTestResult(test, tree) | |
133 | |
134 def for_each_test(self, handler): | |
135 LayoutTestResults._for_each_test(self._test_result_tree(), handler, '') | |
136 | |
137 @staticmethod | |
138 def _for_each_test(tree, handler, prefix=''): | |
139 for key in tree: | |
140 new_prefix = (prefix + '/' + key) if prefix else key | |
141 if 'actual' not in tree[key]: | |
142 LayoutTestResults._for_each_test(tree[key], handler, new_prefix) | |
143 else: | |
144 handler(LayoutTestResult(new_prefix, tree[key])) | |
145 | |
146 def _test_result_tree(self): | |
147 return self._results['tests'] | |
148 | |
149 def _filter_tests(self, result_filter): | |
150 """Returns LayoutTestResult objects for tests which pass the given filte
r.""" | |
151 results = [] | |
152 | |
153 def add_if_passes(result): | |
154 if result_filter(result): | |
155 results.append(result) | |
156 | |
157 LayoutTestResults._for_each_test(self._test_result_tree(), add_if_passes
) | |
158 return sorted(results, key=lambda r: r.test_name()) | |
159 | |
160 def didnt_run_as_expected_results(self): | |
161 # TODO(qyearsley): Rename this method. | |
162 return self._filter_tests(lambda r: not r.did_run_as_expected()) | |
OLD | NEW |