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

Side by Side Diff: tools/valgrind/valgrind_test.py

Issue 27079: Support for running unit-tests under valgrind on Mac (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 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/valgrind/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-2008 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2006-2008 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 # purify_test.py 6 # purify_test.py
7 7
8 '''Runs an exe through Valgrind and puts the intermediate files in a 8 '''Runs an exe through Valgrind and puts the intermediate files in a
9 directory. 9 directory.
10 ''' 10 '''
11 11
12 import datetime 12 import datetime
13 import glob 13 import glob
14 import logging 14 import logging
15 import optparse 15 import optparse
16 import os 16 import os
17 import re
18 import shutil 17 import shutil
19 import sys 18 import sys
20 import time
21
22 import google.path_utils
23 19
24 import common 20 import common
25 21
26 import valgrind_analyze 22 import valgrind_analyze
27 23
28 rmtree = shutil.rmtree 24 rmtree = shutil.rmtree
29 25
30 class Valgrind(): 26 class Valgrind(object):
27
28 """Abstract class for running Valgrind.
29
30 Always subclass this and implement ValgrindCommand() with platform specific
31 stuff.
32 """
33
31 TMP_DIR = "valgrind.tmp" 34 TMP_DIR = "valgrind.tmp"
32 35
33 def __init__(self): 36 def __init__(self):
34 self._suppressions_files = [] 37 self._suppressions_files = []
38 # If we have a valgrind.tmp directory, we failed to cleanup last time.
39 if os.path.exists(self.TMP_DIR):
40 shutil.rmtree(self.TMP_DIR)
41 os.mkdir(self.TMP_DIR)
35 42
36 def CreateOptionParser(self): 43 def CreateOptionParser(self):
37 self._parser = optparse.OptionParser("usage: %prog [options] <program to " 44 self._parser = optparse.OptionParser("usage: %prog [options] <program to "
38 "test>") 45 "test>")
39 self._parser.add_option("-e", "--echo_to_stdout",
40 dest="echo_to_stdout", action="store_true", default=False,
41 help="echo purify output to standard output")
42 self._parser.add_option("-t", "--timeout", 46 self._parser.add_option("-t", "--timeout",
43 dest="timeout", metavar="TIMEOUT", default=10000, 47 dest="timeout", metavar="TIMEOUT", default=10000,
44 help="timeout in seconds for the run (default 10000)") 48 help="timeout in seconds for the run (default 10000)")
45 self._parser.add_option("", "--source_dir", 49 self._parser.add_option("", "--source_dir",
46 help="path to top of source tree for this build" 50 help="path to top of source tree for this build"
47 "(used to normalize source paths in baseline)") 51 "(used to normalize source paths in baseline)")
48 self._parser.add_option("", "--suppressions", default=["."], 52 self._parser.add_option("", "--suppressions", default=["."],
49 action="append", 53 action="append",
50 help="path to a valgrind suppression file") 54 help="path to a valgrind suppression file")
51 self._parser.add_option("", "--generate_suppressions", action="store_true", 55 self._parser.add_option("", "--generate_suppressions", action="store_true",
52 default=False, 56 default=False,
53 help="Skip analysis and generate suppressions") 57 help="Skip analysis and generate suppressions")
54 self._parser.description = __doc__ 58 self._parser.description = __doc__
55 59
56 def ParseArgv(self): 60 def ParseArgv(self):
57 self.CreateOptionParser() 61 self.CreateOptionParser()
58 self._options, self._args = self._parser.parse_args() 62 self._options, self._args = self._parser.parse_args()
59 self._timeout = int(self._options.timeout) 63 self._timeout = int(self._options.timeout)
60 self._suppressions = self._options.suppressions 64 self._suppressions = self._options.suppressions
61 self._generate_suppressions = self._options.generate_suppressions 65 self._generate_suppressions = self._options.generate_suppressions
62 self._source_dir = self._options.source_dir 66 self._source_dir = self._options.source_dir
63 return True 67 return True
64 68
65 def Setup(self): 69 def Setup(self):
66 return self.ParseArgv() 70 return self.ParseArgv()
67 71
72 def ValgrindCommand(self):
73 """Get the valgrind command to run."""
74 raise RuntimeError, "Never use Valgrind directly. Always subclass and " \
75 "implement ValgrindCommand() at least"
76
68 def Execute(self): 77 def Execute(self):
69 ''' Execute the app to be tested after successful instrumentation. 78 ''' Execute the app to be tested after successful instrumentation.
70 Full execution command-line provided by subclassers via proc.''' 79 Full execution command-line provided by subclassers via proc.'''
71 logging.info("starting execution...") 80 logging.info("starting execution...")
72 # note that self._args begins with the exe to be run
73 # TODO(erg): We probably want to get a version of valgrind that supports
74 # the "--track-origins" option...
75 proc = ["valgrind", "--smc-check=all", "--leak-check=full",
76 "--num-callers=30"]
77 81
78 # Either generate suppressions or load them. 82 proc = self.ValgrindCommand()
79 if self._generate_suppressions:
80 proc += ["--gen-suppressions=all"]
81 else:
82 proc += ["--xml=yes"]
83
84 suppression_count = 0
85 for suppression_file in self._suppressions:
86 if os.path.exists(suppression_file):
87 suppression_count += 1
88 proc += ["--suppressions=%s" % suppression_file]
89
90 if not suppression_count:
91 logging.warning("WARNING: NOT USING SUPPRESSIONS!")
92
93 proc += ["--log-file=" + self.TMP_DIR + "/valgrind.%p"] + self._args
94
95 # If we have a valgrind.tmp directory, we failed to cleanup last time.
96 if os.path.exists(self.TMP_DIR):
97 shutil.rmtree(self.TMP_DIR)
98 os.mkdir(self.TMP_DIR)
99 common.RunSubprocess(proc, self._timeout) 83 common.RunSubprocess(proc, self._timeout)
100 84
101 # Always return true, even if running the subprocess failed. We depend on 85 # Always return true, even if running the subprocess failed. We depend on
102 # Analyze to determine if the run was valid. (This behaviour copied from 86 # Analyze to determine if the run was valid. (This behaviour copied from
103 # the purify_test.py script.) 87 # the purify_test.py script.)
104 return True 88 return True
105 89
106 def Analyze(self): 90 def Analyze(self):
107 # Glob all the files in the "valgrind.tmp" directory 91 # Glob all the files in the "valgrind.tmp" directory
108 filenames = glob.glob(self.TMP_DIR + "/valgrind.*") 92 filenames = glob.glob(self.TMP_DIR + "/valgrind.*")
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 end = datetime.datetime.now() 128 end = datetime.datetime.now()
145 seconds = (end - start).seconds 129 seconds = (end - start).seconds
146 hours = seconds / 3600 130 hours = seconds / 3600
147 seconds = seconds % 3600 131 seconds = seconds % 3600
148 minutes = seconds / 60 132 minutes = seconds / 60
149 seconds = seconds % 60 133 seconds = seconds % 60
150 logging.info("elapsed time: %02d:%02d:%02d" % (hours, minutes, seconds)) 134 logging.info("elapsed time: %02d:%02d:%02d" % (hours, minutes, seconds))
151 return retcode 135 return retcode
152 136
153 137
138 class ValgrindLinux(Valgrind):
139
140 """Valgrind on Linux."""
141
142 def __init__(self):
143 Valgrind.__init__(self)
144
145 def ValgrindCommand(self):
146 """Get the valgrind command to run."""
147 # note that self._args begins with the exe to be run
148 # TODO(erg): We probably want to get a version of valgrind that supports
149 # the "--track-origins" option...
150 proc = ["valgrind", "--smc-check=all", "--leak-check=full",
151 "--num-callers=30"]
152
153 # Either generate suppressions or load them.
154 if self._generate_suppressions:
155 proc += ["--gen-suppressions=all"]
156 else:
157 proc += ["--xml=yes"]
158
159 suppression_count = 0
160 for suppression_file in self._suppressions:
161 if os.path.exists(suppression_file):
162 suppression_count += 1
163 proc += ["--suppressions=%s" % suppression_file]
164
165 if not suppression_count:
166 logging.warning("WARNING: NOT USING SUPPRESSIONS!")
167
168 proc += ["--log-file=" + self.TMP_DIR + "/valgrind.%p"] + self._args
169 return proc
170
171
172 class ValgrindMac(Valgrind):
173
174 """Valgrind on Mac OS X.
175
176 Valgrind on OS X does not support suppressions (yet).
177 """
178
179 def __init__(self):
180 Valgrind.__init__(self)
181
182 def ValgrindCommand(self):
183 """Get the valgrind command to run."""
184 proc = ["valgrind", "--leak-check=full"]
185 proc += ["--log-file=" + self.TMP_DIR + "/valgrind.%p"] + self._args
186 return proc
187
188 def Analyze(self):
189 # TODO(nirnimesh): Implement analysis later. Valgrind on Mac is new so
190 # analysis might not be useful until we have stable output from valgring
191 return 0
192
154 193
155 if __name__ == "__main__": 194 if __name__ == "__main__":
156 valgrind = Valgrind() 195 if sys.platform == 'darwin': # Mac
157 retcode = valgrind.Main() 196 valgrind = ValgrindMac()
158 sys.exit(retcode) 197 retcode = valgrind.Main()
159 198 sys.exit(retcode)
160 199 elif sys.platform == 'linux2': # Linux
200 valgrind = ValgrindLinux()
201 retcode = valgrind.Main()
202 sys.exit(retcode)
203 else:
204 logging.error("Unknown platform: %s" % sys.platform)
205 sys.exit(1)
OLDNEW
« no previous file with comments | « tools/valgrind/chrome_tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698