OLD | NEW |
1 # Copyright (C) 2010 Google Inc. All rights reserved. | 1 # Copyright (C) 2010 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 13 matching lines...) Expand all Loading... |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | 28 |
29 import json | 29 import json |
30 import logging | 30 import logging |
31 | 31 |
32 _log = logging.getLogger(__name__) | 32 _log = logging.getLogger(__name__) |
33 | 33 |
34 _JSON_PREFIX = "ADD_RESULTS(" | 34 _JSON_PREFIX = 'ADD_RESULTS(' |
35 _JSON_SUFFIX = ");" | 35 _JSON_SUFFIX = ');' |
36 | 36 |
37 | 37 |
38 def has_json_wrapper(string): | 38 def has_json_wrapper(string): |
39 return string.startswith(_JSON_PREFIX) and string.endswith(_JSON_SUFFIX) | 39 return string.startswith(_JSON_PREFIX) and string.endswith(_JSON_SUFFIX) |
40 | 40 |
41 | 41 |
42 def strip_json_wrapper(json_content): | 42 def strip_json_wrapper(json_content): |
43 # FIXME: Kill this code once the server returns json instead of jsonp. | 43 # FIXME: Kill this code once the server returns json instead of jsonp. |
44 if has_json_wrapper(json_content): | 44 if has_json_wrapper(json_content): |
45 return json_content[len(_JSON_PREFIX):len(json_content) - len(_JSON_SUFF
IX)] | 45 return json_content[len(_JSON_PREFIX):len(json_content) - len(_JSON_SUFF
IX)] |
46 return json_content | 46 return json_content |
47 | 47 |
48 | 48 |
49 def load_json(filesystem, file_path): | 49 def load_json(filesystem, file_path): |
50 content = filesystem.read_text_file(file_path) | 50 content = filesystem.read_text_file(file_path) |
51 content = strip_json_wrapper(content) | 51 content = strip_json_wrapper(content) |
52 return json.loads(content) | 52 return json.loads(content) |
53 | 53 |
54 | 54 |
55 def write_json(filesystem, json_object, file_path, callback=None): | 55 def write_json(filesystem, json_object, file_path, callback=None): |
56 # Specify separators in order to get compact encoding. | 56 # Specify separators in order to get compact encoding. |
57 json_string = json.dumps(json_object, separators=(',', ':')) | 57 json_string = json.dumps(json_object, separators=(',', ':')) |
58 if callback: | 58 if callback: |
59 json_string = callback + "(" + json_string + ");" | 59 json_string = callback + '(' + json_string + ');' |
60 filesystem.write_text_file(file_path, json_string) | 60 filesystem.write_text_file(file_path, json_string) |
61 | 61 |
62 | 62 |
63 def convert_trie_to_flat_paths(trie, prefix=None): | 63 def convert_trie_to_flat_paths(trie, prefix=None): |
64 """Converts the directory structure in the given trie to flat paths, prepend
ing a prefix to each.""" | 64 """Converts the directory structure in the given trie to flat paths, prepend
ing a prefix to each.""" |
65 result = {} | 65 result = {} |
66 for name, data in trie.iteritems(): | 66 for name, data in trie.iteritems(): |
67 if prefix: | 67 if prefix: |
68 name = prefix + "/" + name | 68 name = prefix + '/' + name |
69 | 69 |
70 if len(data) and not "results" in data: | 70 if len(data) and not 'results' in data: |
71 result.update(convert_trie_to_flat_paths(data, name)) | 71 result.update(convert_trie_to_flat_paths(data, name)) |
72 else: | 72 else: |
73 result[name] = data | 73 result[name] = data |
74 | 74 |
75 return result | 75 return result |
76 | 76 |
77 | 77 |
78 def add_path_to_trie(path, value, trie): | 78 def add_path_to_trie(path, value, trie): |
79 """Inserts a single flat directory path and associated value into a director
y trie structure.""" | 79 """Inserts a single flat directory path and associated value into a director
y trie structure.""" |
80 if not "/" in path: | 80 if not '/' in path: |
81 trie[path] = value | 81 trie[path] = value |
82 return | 82 return |
83 | 83 |
84 directory, slash, rest = path.partition("/") | 84 directory, slash, rest = path.partition('/') |
85 if not directory in trie: | 85 if not directory in trie: |
86 trie[directory] = {} | 86 trie[directory] = {} |
87 add_path_to_trie(rest, value, trie[directory]) | 87 add_path_to_trie(rest, value, trie[directory]) |
88 | 88 |
89 | 89 |
90 def test_timings_trie(individual_test_timings): | 90 def test_timings_trie(individual_test_timings): |
91 """Breaks a test name into chunks by directory and puts the test time as a v
alue in the lowest part, e.g. | 91 """Breaks a test name into chunks by directory and puts the test time as a v
alue in the lowest part, e.g. |
92 foo/bar/baz.html: 1ms | 92 foo/bar/baz.html: 1ms |
93 foo/bar/baz1.html: 3ms | 93 foo/bar/baz1.html: 3ms |
94 | 94 |
95 becomes | 95 becomes |
96 foo: { | 96 foo: { |
97 bar: { | 97 bar: { |
98 baz.html: 1, | 98 baz.html: 1, |
99 baz1.html: 3 | 99 baz1.html: 3 |
100 } | 100 } |
101 } | 101 } |
102 """ | 102 """ |
103 trie = {} | 103 trie = {} |
104 for test_result in individual_test_timings: | 104 for test_result in individual_test_timings: |
105 test = test_result.test_name | 105 test = test_result.test_name |
106 | 106 |
107 add_path_to_trie(test, int(1000 * test_result.test_run_time), trie) | 107 add_path_to_trie(test, int(1000 * test_result.test_run_time), trie) |
108 | 108 |
109 return trie | 109 return trie |
110 | 110 |
111 | 111 |
112 # FIXME: We already have a TestResult class in test_results.py | 112 # FIXME: We already have a TestResult class in test_results.py |
113 class TestResult(object): | 113 class TestResult(object): |
| 114 |
114 """A simple class that represents a single test result.""" | 115 """A simple class that represents a single test result.""" |
115 | 116 |
116 # Test modifier constants. | 117 # Test modifier constants. |
117 (NONE, FAILS, FLAKY, DISABLED) = range(4) | 118 (NONE, FAILS, FLAKY, DISABLED) = range(4) |
118 | 119 |
119 def __init__(self, test, failed=False, elapsed_time=0): | 120 def __init__(self, test, failed=False, elapsed_time=0): |
120 self.test_name = test | 121 self.test_name = test |
121 self.failed = failed | 122 self.failed = failed |
122 self.test_run_time = elapsed_time | 123 self.test_run_time = elapsed_time |
123 | 124 |
124 test_name = test | 125 test_name = test |
125 try: | 126 try: |
126 test_name = test.split('.')[1] | 127 test_name = test.split('.')[1] |
127 except IndexError: | 128 except IndexError: |
128 _log.warn("Invalid test name: %s.", test) | 129 _log.warn('Invalid test name: %s.', test) |
129 pass | 130 pass |
130 | 131 |
131 if test_name.startswith('FAILS_'): | 132 if test_name.startswith('FAILS_'): |
132 self.modifier = self.FAILS | 133 self.modifier = self.FAILS |
133 elif test_name.startswith('FLAKY_'): | 134 elif test_name.startswith('FLAKY_'): |
134 self.modifier = self.FLAKY | 135 self.modifier = self.FLAKY |
135 elif test_name.startswith('DISABLED_'): | 136 elif test_name.startswith('DISABLED_'): |
136 self.modifier = self.DISABLED | 137 self.modifier = self.DISABLED |
137 else: | 138 else: |
138 self.modifier = self.NONE | 139 self.modifier = self.NONE |
139 | 140 |
140 def fixable(self): | 141 def fixable(self): |
141 return self.failed or self.modifier == self.DISABLED | 142 return self.failed or self.modifier == self.DISABLED |
OLD | NEW |