| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 from third_party import asan_symbolize | 7 from third_party import asan_symbolize |
| 8 | 8 |
| 9 import argparse | 9 import argparse |
| 10 import base64 | 10 import base64 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 # is located in the product dir. | 156 # is located in the product dir. |
| 157 outermost_bundle = bundle_positions[0] | 157 outermost_bundle = bundle_positions[0] |
| 158 product_dir = path_parts[:outermost_bundle] | 158 product_dir = path_parts[:outermost_bundle] |
| 159 # In case 2 this is the same as |outermost_bundle|. | 159 # In case 2 this is the same as |outermost_bundle|. |
| 160 innermost_bundle = bundle_positions[-1] | 160 innermost_bundle = bundle_positions[-1] |
| 161 dsym_path = product_dir + [path_parts[innermost_bundle]] | 161 dsym_path = product_dir + [path_parts[innermost_bundle]] |
| 162 result = '%s.dSYM' % os.path.join(*dsym_path) | 162 result = '%s.dSYM' % os.path.join(*dsym_path) |
| 163 return [result] | 163 return [result] |
| 164 | 164 |
| 165 | 165 |
| 166 # We want our output to match base::EscapeJSONString(), which produces | |
| 167 # doubly-escaped strings. The first escaping pass is handled by this class. The | |
| 168 # second pass happens when JSON data is dumped to file. | |
| 169 class StringEncoder(json.JSONEncoder): | |
| 170 def __init__(self): | |
| 171 json.JSONEncoder.__init__(self) | |
| 172 | |
| 173 def encode(self, s): | |
| 174 assert(isinstance(s, basestring)) | |
| 175 # Don't die on invalid utf-8 sequences. | |
| 176 s = s.decode('utf-8', 'replace') | |
| 177 encoded = json.JSONEncoder.encode(self, s) | |
| 178 assert(len(encoded) >= 2) | |
| 179 assert(encoded[0] == '"') | |
| 180 assert(encoded[-1] == '"') | |
| 181 encoded = encoded[1:-1] | |
| 182 # Special case from base::EscapeJSONString(). | |
| 183 encoded = encoded.replace('<', '\u003C') | |
| 184 return encoded | |
| 185 | |
| 186 | |
| 187 class JSONTestRunSymbolizer(object): | 166 class JSONTestRunSymbolizer(object): |
| 188 def __init__(self, symbolization_loop): | 167 def __init__(self, symbolization_loop): |
| 189 self.symbolization_loop = symbolization_loop | 168 self.symbolization_loop = symbolization_loop |
| 190 | 169 |
| 191 def symbolize_snippet(self, snippet): | 170 def symbolize_snippet(self, snippet): |
| 192 symbolized_lines = [] | 171 symbolized_lines = [] |
| 193 for line in snippet.split('\n'): | 172 for line in snippet.split('\n'): |
| 194 symbolized_lines += self.symbolization_loop.process_line(line) | 173 symbolized_lines += self.symbolization_loop.process_line(line) |
| 195 return '\n'.join(symbolized_lines) | 174 return '\n'.join(symbolized_lines) |
| 196 | 175 |
| 197 def symbolize(self, test_run): | 176 def symbolize(self, test_run): |
| 198 original_snippet = base64.b64decode(test_run['output_snippet_base64']) | 177 original_snippet = base64.b64decode(test_run['output_snippet_base64']) |
| 199 symbolized_snippet = self.symbolize_snippet(original_snippet) | 178 symbolized_snippet = self.symbolize_snippet(original_snippet) |
| 200 if symbolized_snippet == original_snippet: | 179 if symbolized_snippet == original_snippet: |
| 201 # No sanitizer reports in snippet. | 180 # No sanitizer reports in snippet. |
| 202 return | 181 return |
| 203 | 182 |
| 204 test_run['original_output_snippet'] = test_run['output_snippet'] | 183 test_run['original_output_snippet'] = test_run['output_snippet'] |
| 205 test_run['original_output_snippet_base64'] = \ | 184 test_run['original_output_snippet_base64'] = \ |
| 206 test_run['output_snippet_base64'] | 185 test_run['output_snippet_base64'] |
| 207 | 186 |
| 208 escaped_snippet = StringEncoder().encode(symbolized_snippet) | 187 test_run['output_snippet'] = symbolized_snippet |
| 209 test_run['output_snippet'] = escaped_snippet | |
| 210 test_run['output_snippet_base64'] = \ | 188 test_run['output_snippet_base64'] = \ |
| 211 base64.b64encode(symbolized_snippet) | 189 base64.b64encode(symbolized_snippet) |
| 212 test_run['snippet_processed_by'] = 'asan_symbolize.py' | 190 test_run['snippet_processed_by'] = 'asan_symbolize.py' |
| 213 # Originally, "lossless" refers to "no Unicode data lost while encoding the | |
| 214 # string". However, since we're applying another kind of transformation | |
| 215 # (symbolization), it doesn't seem right to consider the snippet lossless. | |
| 216 test_run['losless_snippet'] = False | |
| 217 | 191 |
| 218 | 192 |
| 219 def symbolize_snippets_in_json(filename, symbolization_loop): | 193 def symbolize_snippets_in_json(filename, symbolization_loop): |
| 220 with open(filename, 'r') as f: | 194 with open(filename, 'r') as f: |
| 221 json_data = json.load(f) | 195 json_data = json.load(f) |
| 222 | 196 |
| 223 test_run_symbolizer = JSONTestRunSymbolizer(symbolization_loop) | 197 test_run_symbolizer = JSONTestRunSymbolizer(symbolization_loop) |
| 224 for iteration_data in json_data['per_iteration_data']: | 198 for iteration_data in json_data['per_iteration_data']: |
| 225 for test_name, test_runs in iteration_data.iteritems(): | 199 for test_name, test_runs in iteration_data.iteritems(): |
| 226 for test_run in test_runs: | 200 for test_run in test_runs: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 | 236 |
| 263 if args.test_summary_json_file: | 237 if args.test_summary_json_file: |
| 264 symbolize_snippets_in_json(args.test_summary_json_file, loop) | 238 symbolize_snippets_in_json(args.test_summary_json_file, loop) |
| 265 else: | 239 else: |
| 266 # Process stdin. | 240 # Process stdin. |
| 267 asan_symbolize.logfile = sys.stdin | 241 asan_symbolize.logfile = sys.stdin |
| 268 loop.process_logfile() | 242 loop.process_logfile() |
| 269 | 243 |
| 270 if __name__ == '__main__': | 244 if __name__ == '__main__': |
| 271 main() | 245 main() |
| OLD | NEW |