| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # heapcheck_test.py | 6 # heapcheck_test.py |
| 7 | 7 |
| 8 """Wrapper for running the test under heapchecker and analyzing the output.""" | 8 """Wrapper for running the test under heapchecker and analyzing the output.""" |
| 9 | 9 |
| 10 import datetime | 10 import datetime |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 0, if all the errors are suppressed and the sanity check passes. | 82 0, if all the errors are suppressed and the sanity check passes. |
| 83 """ | 83 """ |
| 84 leak_report = re.compile( | 84 leak_report = re.compile( |
| 85 'Leak of ([0-9]*) bytes in ([0-9]*) objects allocated from:') | 85 'Leak of ([0-9]*) bytes in ([0-9]*) objects allocated from:') |
| 86 stack_line = re.compile('\s*@\s*(?:0x)?[0-9a-fA-F]+\s*([^\n]*)') | 86 stack_line = re.compile('\s*@\s*(?:0x)?[0-9a-fA-F]+\s*([^\n]*)') |
| 87 return_code = 0 | 87 return_code = 0 |
| 88 # leak signature: [number of bytes, number of objects] | 88 # leak signature: [number of bytes, number of objects] |
| 89 cur_leak_signature = None | 89 cur_leak_signature = None |
| 90 cur_stack = [] | 90 cur_stack = [] |
| 91 cur_report = [] | 91 cur_report = [] |
| 92 reported_hashes = {} |
| 92 # Statistics grouped by suppression description: | 93 # Statistics grouped by suppression description: |
| 93 # [hit count, bytes, objects]. | 94 # [hit count, bytes, objects]. |
| 94 used_suppressions = {} | 95 used_suppressions = {} |
| 95 for line in log_lines: | 96 for line in log_lines: |
| 96 line = line.rstrip() # remove the trailing \n | 97 line = line.rstrip() # remove the trailing \n |
| 97 match = stack_line.match(line) | 98 match = stack_line.match(line) |
| 98 if match: | 99 if match: |
| 99 cur_stack.append(match.groups()[0]) | 100 cur_stack.append(match.groups()[0]) |
| 100 cur_report.append(line) | 101 cur_report.append(line) |
| 101 continue | 102 continue |
| 102 else: | 103 else: |
| 103 if cur_stack: | 104 if cur_stack: |
| 104 # Try to find the suppression that applies to the current leak stack. | 105 # Try to find the suppression that applies to the current leak stack. |
| 105 description = '' | 106 description = '' |
| 106 for supp in self._suppressions: | 107 for supp in self._suppressions: |
| 107 if supp.Match(cur_stack): | 108 if supp.Match(cur_stack): |
| 108 cur_stack = [] | 109 cur_stack = [] |
| 109 description = supp.description | 110 description = supp.description |
| 110 break | 111 break |
| 111 if cur_stack: | 112 if cur_stack: |
| 112 if not cur_leak_signature: | 113 if not cur_leak_signature: |
| 113 print 'Missing leak signature for the following stack: ' | 114 print 'Missing leak signature for the following stack: ' |
| 114 for frame in cur_stack: | 115 for frame in cur_stack: |
| 115 print ' ' + frame | 116 print ' ' + frame |
| 116 print 'Aborting...' | 117 print 'Aborting...' |
| 117 return 3 | 118 return 3 |
| 118 # Print the report and set the return code to 1. | 119 error_hash = hash("".join(cur_stack)) & 0xffffffffffffffff |
| 119 print ('Leak of %d bytes in %d objects allocated from:' | 120 if error_hash not in reported_hashes: |
| 120 % tuple(cur_leak_signature)) | 121 reported_hashes[error_hash] = 1 |
| 121 print '\n'.join(cur_report) | 122 # Print the report and set the return code to 1. |
| 122 return_code = 1 | 123 print ('Leak of %d bytes in %d objects allocated from:' |
| 123 # Generate the suppression iff the stack contains more than one | 124 % tuple(cur_leak_signature)) |
| 124 # frame (otherwise it's likely to be broken) | 125 print '\n'.join(cur_report) |
| 125 if len(cur_stack) > 1: | 126 return_code = 1 |
| 126 print '\nSuppression (error hash=#%016X#):\n{' \ | 127 # Generate the suppression iff the stack contains more than one |
| 127 % (hash("".join(cur_stack)) & 0xffffffffffffffff) | 128 # frame (otherwise it's likely to be broken) |
| 128 print ' <insert_a_suppression_name_here>' | 129 if len(cur_stack) > 1: |
| 129 print ' Heapcheck:Leak' | 130 print '\nSuppression (error hash=#%016X#):\n{' % (error_hash) |
| 130 for frame in cur_stack: | 131 print ' <insert_a_suppression_name_here>' |
| 131 print ' fun:' + frame | 132 print ' Heapcheck:Leak' |
| 132 print '}\n\n\n' | 133 for frame in cur_stack: |
| 133 else: | 134 print ' fun:' + frame |
| 134 print ('This stack may be broken due to omitted frame pointers. ' | 135 print '}\n\n\n' |
| 135 'It is not recommended to suppress it.') | 136 else: |
| 137 print ('This stack may be broken due to omitted frame pointers.' |
| 138 ' It is not recommended to suppress it.') |
| 136 else: | 139 else: |
| 137 # Update the suppressions histogram. | 140 # Update the suppressions histogram. |
| 138 if description in used_suppressions: | 141 if description in used_suppressions: |
| 139 hits, bytes, objects = used_suppressions[description] | 142 hits, bytes, objects = used_suppressions[description] |
| 140 hits += 1 | 143 hits += 1 |
| 141 bytes += cur_leak_signature[0] | 144 bytes += cur_leak_signature[0] |
| 142 objects += cur_leak_signature[1] | 145 objects += cur_leak_signature[1] |
| 143 used_suppressions[description] = [hits, bytes, objects] | 146 used_suppressions[description] = [hits, bytes, objects] |
| 144 else: | 147 else: |
| 145 used_suppressions[description] = [1] + cur_leak_signature | 148 used_suppressions[description] = [1] + cur_leak_signature |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 'http://dev.chromium.org/developers/how-tos/' | 206 'http://dev.chromium.org/developers/how-tos/' |
| 204 'using-the-heap-leak-checker') | 207 'using-the-heap-leak-checker') |
| 205 return retcode | 208 return retcode |
| 206 | 209 |
| 207 | 210 |
| 208 def RunTool(args, supp_files, module): | 211 def RunTool(args, supp_files, module): |
| 209 tool = HeapcheckWrapper(supp_files) | 212 tool = HeapcheckWrapper(supp_files) |
| 210 MODULES_TO_SANITY_CHECK = ["base"] | 213 MODULES_TO_SANITY_CHECK = ["base"] |
| 211 check_sanity = module in MODULES_TO_SANITY_CHECK | 214 check_sanity = module in MODULES_TO_SANITY_CHECK |
| 212 return tool.Main(args[1:], check_sanity) | 215 return tool.Main(args[1:], check_sanity) |
| OLD | NEW |