Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: tools/heapcheck/heapcheck_test.py

Issue 596085: Make the heapheck runner recognize the sanity tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/heapcheck/chrome_tests.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 import logging 11 import logging
12 import os 12 import os
13 import re 13 import re
14 14
15 import common 15 import common
16 import google.path_utils 16 import google.path_utils
17 import suppressions 17 import suppressions
18 18
19 19
20 class HeapcheckWrapper(object): 20 class HeapcheckWrapper(object):
21 TMP_FILE = 'heapcheck.log' 21 TMP_FILE = 'heapcheck.log'
22 SANITY_TEST_SUPPRESSION = "Heapcheck sanity test"
22 23
23 def __init__(self, supp_files): 24 def __init__(self, supp_files):
24 self._mode = 'strict' 25 self._mode = 'strict'
25 self._timeout = 1200 26 self._timeout = 1200
26 self._nocleanup_on_exit = False 27 self._nocleanup_on_exit = False
27 self._suppressions = [] 28 self._suppressions = []
28 for fname in supp_files: 29 for fname in supp_files:
29 self._suppressions.extend(suppressions.ReadSuppressionsFromFile(fname)) 30 self._suppressions.extend(suppressions.ReadSuppressionsFromFile(fname))
30 if os.path.exists(self.TMP_FILE): 31 if os.path.exists(self.TMP_FILE):
31 os.remove(self.TMP_FILE) 32 os.remove(self.TMP_FILE)
(...skipping 19 matching lines...) Expand all
51 '/../../third_party/tcmalloc/chromium/src/pprof') 52 '/../../third_party/tcmalloc/chromium/src/pprof')
52 self.PutEnvAndLog('LD_PRELOAD', '/usr/lib/debug/libstdc++.so') 53 self.PutEnvAndLog('LD_PRELOAD', '/usr/lib/debug/libstdc++.so')
53 54
54 common.RunSubprocess(proc, self._timeout) 55 common.RunSubprocess(proc, self._timeout)
55 56
56 # Always return true, even if running the subprocess failed. We depend on 57 # Always return true, even if running the subprocess failed. We depend on
57 # Analyze to determine if the run was valid. (This behaviour copied from 58 # Analyze to determine if the run was valid. (This behaviour copied from
58 # the purify_test.py script.) 59 # the purify_test.py script.)
59 return True 60 return True
60 61
61 def Analyze(self, log_lines): 62 def Analyze(self, log_lines, check_sanity=False):
62 """Analyzes the app's output and applies suppressions to the reports. 63 """Analyzes the app's output and applies suppressions to the reports.
63 64
64 Analyze() searches the logs for leak reports and tries to apply 65 Analyze() searches the logs for leak reports and tries to apply
65 suppressions to them. Unsuppressed reports and other log messages are 66 suppressions to them. Unsuppressed reports and other log messages are
66 dumped as is. 67 dumped as is.
67 68
69 If |check_sanity| is True, the list of suppressed reports is searched for a
70 report starting with SANITY_TEST_SUPPRESSION. If there isn't one, Analyze
71 returns 2 regardless of the unsuppressed reports.
72
68 Args: 73 Args:
69 log_lines: An iterator over the app's log lines. 74 log_lines: An iterator over the app's log lines.
75 check_sanity: A flag that determines whether we should check the tool's
76 sanity.
70 Returns: 77 Returns:
71 1, if unsuppressed reports remain in the output, 0 otherwise. 78 2, if the sanity check fails,
79 1, if unsuppressed reports remain in the output and the sanity check
80 passes,
81 0, if all the errors are suppressed and the sanity check passes.
72 """ 82 """
73 leak_report = re.compile( 83 leak_report = re.compile(
74 'Leak of ([0-9]*) bytes in ([0-9]*) objects allocated from:') 84 'Leak of ([0-9]*) bytes in ([0-9]*) objects allocated from:')
75 stack_line = re.compile('\s*@\s*0x[0-9a-fA-F]*\s*(\S*)') 85 stack_line = re.compile('\s*@\s*[0-9a-fA-F]*\s*(\S*)')
76 return_code = 0 86 return_code = 0
77 # leak signature: [number of bytes, number of objects] 87 # leak signature: [number of bytes, number of objects]
78 cur_leak_signature = None 88 cur_leak_signature = None
79 cur_stack = [] 89 cur_stack = []
80 cur_report = [] 90 cur_report = []
81 # Statistics grouped by suppression description: 91 # Statistics grouped by suppression description:
82 # [hit count, bytes, objects]. 92 # [hit count, bytes, objects].
83 used_suppressions = {} 93 used_suppressions = {}
84 for line in log_lines: 94 for line in log_lines:
85 line = line.rstrip() # remove the trailing \n 95 line = line.rstrip() # remove the trailing \n
(...skipping 29 matching lines...) Expand all
115 used_suppressions[description] = [1] + cur_leak_signature 125 used_suppressions[description] = [1] + cur_leak_signature
116 cur_stack = [] 126 cur_stack = []
117 cur_report = [] 127 cur_report = []
118 cur_leak_signature = None 128 cur_leak_signature = None
119 match = leak_report.match(line) 129 match = leak_report.match(line)
120 if match: 130 if match:
121 cur_leak_signature = map(int, match.groups()) 131 cur_leak_signature = map(int, match.groups())
122 else: 132 else:
123 print line 133 print line
124 # Print the list of suppressions used. 134 # Print the list of suppressions used.
135 is_sane = False
125 if used_suppressions: 136 if used_suppressions:
126 print 137 print
127 print '-----------------------------------------------------' 138 print '-----------------------------------------------------'
128 print 'Suppressions used:' 139 print 'Suppressions used:'
129 print ' count bytes objects name' 140 print ' count bytes objects name'
130 histo = {} 141 histo = {}
131 for description in used_suppressions: 142 for description in used_suppressions:
143 if description.startswith(HeapcheckWrapper.SANITY_TEST_SUPPRESSION):
144 is_sane = True
132 hits, bytes, objects = used_suppressions[description] 145 hits, bytes, objects = used_suppressions[description]
133 line = '%8d %8d %8d %s' % (hits, bytes, objects, description) 146 line = '%8d %8d %8d %s' % (hits, bytes, objects, description)
134 if hits in histo: 147 if hits in histo:
135 histo[hits].append(line) 148 histo[hits].append(line)
136 else: 149 else:
137 histo[hits] = [line] 150 histo[hits] = [line]
138 keys = histo.keys() 151 keys = histo.keys()
139 keys.sort() 152 keys.sort()
140 for count in keys: 153 for count in keys:
141 for line in histo[count]: 154 for line in histo[count]:
142 print line 155 print line
143 print '-----------------------------------------------------' 156 print '-----------------------------------------------------'
157 if is_sane:
158 return return_code
159 else:
160 logging.error("Sanity check failed")
161 return 2
144 162
145 return return_code 163 def RunTestsAndAnalyze(self, check_sanity):
146
147 def RunTestsAndAnalyze(self):
148 self.Execute() 164 self.Execute()
149 log_file = file(self.TMP_FILE, 'r') 165 log_file = file(self.TMP_FILE, 'r')
150 ret = self.Analyze(log_file) 166 ret = self.Analyze(log_file, check_sanity)
151 log_file.close() 167 log_file.close()
152 return ret 168 return ret
153 169
154 def Main(self, args): 170 def Main(self, args, check_sanity=False):
155 self._args = args 171 self._args = args
156 start = datetime.datetime.now() 172 start = datetime.datetime.now()
157 retcode = -1 173 retcode = -1
158 retcode = self.RunTestsAndAnalyze() 174 retcode = self.RunTestsAndAnalyze(check_sanity)
159 end = datetime.datetime.now() 175 end = datetime.datetime.now()
160 seconds = (end - start).seconds 176 seconds = (end - start).seconds
161 hours = seconds / 3600 177 hours = seconds / 3600
162 seconds %= 3600 178 seconds %= 3600
163 minutes = seconds / 60 179 minutes = seconds / 60
164 seconds %= 60 180 seconds %= 60
165 logging.info('elapsed time: %02d:%02d:%02d', hours, minutes, seconds) 181 logging.info('elapsed time: %02d:%02d:%02d', hours, minutes, seconds)
166 return retcode 182 return retcode
167 183
168 184
169 def RunTool(args, supp_files): 185 def RunTool(args, supp_files, module):
170 tool = HeapcheckWrapper(supp_files) 186 tool = HeapcheckWrapper(supp_files)
171 return tool.Main(args[1:]) 187 MODULES_TO_SANITY_CHECK = ["base"]
188 check_sanity = module in MODULES_TO_SANITY_CHECK
189 return tool.Main(args[1:], check_sanity)
OLDNEW
« no previous file with comments | « tools/heapcheck/chrome_tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698