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

Side by Side Diff: tools/drmemory/scripts/pdfium_tests.py

Issue 1452293002: Add Dr. Memory tool (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: remove old chromium tests in pdfium_test.py Created 5 years, 1 month 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
« no previous file with comments | « tools/drmemory/scripts/pdfium_tests.bat ('k') | tools/drmemory/scripts/valgrind_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 ''' Runs various chrome tests through valgrind_test.py.'''
7
8 import glob
9 import logging
10 import multiprocessing
Lei Zhang 2015/11/17 23:33:04 no longer used
zhaoqin 2015/11/18 16:26:36 Done.
11 import optparse
12 import os
13 import stat
Lei Zhang 2015/11/17 23:33:04 no longer used
zhaoqin 2015/11/18 16:26:36 Done.
14 import subprocess
15 import sys
16
17 import logging_utils
18 import path_utils
19
20 import common
21 import valgrind_test
22
23 class TestNotFound(Exception): pass
24
25 class MultipleGTestFiltersSpecified(Exception): pass
26
27 class BuildDirNotFound(Exception): pass
28
29 class BuildDirAmbiguous(Exception): pass
30
31 class ExecutableNotFound(Exception): pass
32
33 class BadBinary(Exception): pass
34
35 class ChromeTests:
36 SLOW_TOOLS = ["memcheck", "drmemory"]
Lei Zhang 2015/11/17 23:33:04 Remove memcheck reference.
zhaoqin 2015/11/18 16:26:36 Done.
37
38 def __init__(self, options, args, test):
39 if ':' in test:
40 (self._test, self._gtest_filter) = test.split(':', 1)
41 else:
42 self._test = test
43 self._gtest_filter = options.gtest_filter
44
45 if self._test not in self._test_list:
46 raise TestNotFound("Unknown test: %s" % test)
47
48 if options.gtest_filter and options.gtest_filter != self._gtest_filter:
49 raise MultipleGTestFiltersSpecified("Can not specify both --gtest_filter "
50 "and --test %s" % test)
51
52 self._options = options
53 self._args = args
54
55 script_dir = path_utils.ScriptDir()
56 # Compute the top of the tree (the "source dir") from the script dir (where
57 # this script lives). We assume that the script dir is in tools/valgrind/
58 # relative to the top of the tree.
59 self._source_dir = os.path.dirname(os.path.dirname(script_dir))
60 # since this path is used for string matching, make sure it's always
61 # an absolute Unix-style path
62 self._source_dir = os.path.abspath(self._source_dir).replace('\\', '/')
63 valgrind_test_script = os.path.join(script_dir, "valgrind_test.py")
64 self._command_preamble = ["--source-dir=%s" % (self._source_dir)]
65
66 if not self._options.build_dir:
67 dirs = [
68 os.path.join(self._source_dir, "xcodebuild", "Debug"),
69 os.path.join(self._source_dir, "out", "Debug"),
70 os.path.join(self._source_dir, "build", "Debug"),
71 ]
72 build_dir = [d for d in dirs if os.path.isdir(d)]
73 if len(build_dir) > 1:
74 raise BuildDirAmbiguous("Found more than one suitable build dir:\n"
75 "%s\nPlease specify just one "
76 "using --build-dir" % ", ".join(build_dir))
77 elif build_dir:
78 self._options.build_dir = build_dir[0]
79 else:
80 self._options.build_dir = None
81
82 if self._options.build_dir:
83 build_dir = os.path.abspath(self._options.build_dir)
84 self._command_preamble += ["--build-dir=%s" % (self._options.build_dir)]
85
86 def _EnsureBuildDirFound(self):
87 if not self._options.build_dir:
88 raise BuildDirNotFound("Oops, couldn't find a build dir, please "
89 "specify it manually using --build-dir")
90
91 def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None):
92 '''Generates the default command array that most tests will use.'''
93 if exe and common.IsWindows():
94 exe += '.exe'
95
96 cmd = list(self._command_preamble)
97
98 # Find all suppressions matching the following pattern:
99 # tools/valgrind/TOOL/suppressions[_PLATFORM].txt
100 # and list them with --suppressions= prefix.
101 script_dir = path_utils.ScriptDir()
102 tool_name = tool.ToolName();
103 suppression_file = os.path.join(script_dir, tool_name, "suppressions.txt")
104 if os.path.exists(suppression_file):
105 cmd.append("--suppressions=%s" % suppression_file)
106 # Platform-specific suppression
107 for platform in common.PlatformNames():
108 platform_suppression_file = \
109 os.path.join(script_dir, tool_name, 'suppressions_%s.txt' % platform)
110 if os.path.exists(platform_suppression_file):
111 cmd.append("--suppressions=%s" % platform_suppression_file)
112
113 if self._options.valgrind_tool_flags:
114 cmd += self._options.valgrind_tool_flags.split(" ")
115 if self._options.keep_logs:
116 cmd += ["--keep_logs"]
117 if valgrind_test_args != None:
118 for arg in valgrind_test_args:
119 cmd.append(arg)
120 if exe:
121 self._EnsureBuildDirFound()
122 exe_path = os.path.join(self._options.build_dir, exe)
123 if not os.path.exists(exe_path):
124 raise ExecutableNotFound("Couldn't find '%s'" % exe_path)
125
126 # Make sure we don't try to test ASan-built binaries
127 # with other dynamic instrumentation-based tools.
128 # TODO(timurrrr): also check TSan and MSan?
129 # `nm` might not be available, so use try-except.
130 try:
131 # Do not perform this check on OS X, as 'nm' on 10.6 can't handle
132 # binaries built with Clang 3.5+.
133 if not common.IsMac():
134 nm_output = subprocess.check_output(["nm", exe_path])
135 if nm_output.find("__asan_init") != -1:
136 raise BadBinary("You're trying to run an executable instrumented "
137 "with AddressSanitizer under %s. Please provide "
138 "an uninstrumented executable." % tool_name)
139 except OSError:
140 pass
141
142 cmd.append(exe_path)
143 # Valgrind runs tests slowly, so slow tests hurt more; show elapased time
144 # so we can find the slowpokes.
145 cmd.append("--gtest_print_time")
146 # Built-in test launcher for gtest-based executables runs tests using
147 # multiple process by default. Force the single-process mode back.
148 cmd.append("--single-process-tests")
149 if self._options.gtest_repeat:
150 cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat)
151 if self._options.gtest_shuffle:
152 cmd.append("--gtest_shuffle")
153 if self._options.gtest_break_on_failure:
154 cmd.append("--gtest_break_on_failure")
155 if self._options.test_launcher_bot_mode:
156 cmd.append("--test-launcher-bot-mode")
157 if self._options.test_launcher_total_shards is not None:
158 cmd.append("--test-launcher-total-shards=%d" % self._options.test_launcher _total_shards)
159 if self._options.test_launcher_shard_index is not None:
160 cmd.append("--test-launcher-shard-index=%d" % self._options.test_launcher_ shard_index)
161 return cmd
162
163 def Run(self):
164 ''' Runs the test specified by command-line argument --test '''
165 logging.info("running test %s" % (self._test))
166 return self._test_list[self._test](self)
167
168 def _AppendGtestFilter(self, tool, name, cmd):
169 '''Append an appropriate --gtest_filter flag to the googletest binary
170 invocation.
171 If the user passed his own filter mentioning only one test, just use it.
172 Othewise, filter out tests listed in the appropriate gtest_exclude files.
173 '''
174 if (self._gtest_filter and
175 ":" not in self._gtest_filter and
176 "?" not in self._gtest_filter and
177 "*" not in self._gtest_filter):
178 cmd.append("--gtest_filter=%s" % self._gtest_filter)
179 return
180
181 filters = []
182 gtest_files_dir = os.path.join(path_utils.ScriptDir(), "gtest_exclude")
183
184 gtest_filter_files = [
185 os.path.join(gtest_files_dir, name + ".gtest-%s.txt" % tool.ToolName())]
186 # Use ".gtest.txt" files only for slow tools, as they now contain
187 # Valgrind- and Dr.Memory-specific filters.
188 # TODO(glider): rename the files to ".gtest_slow.txt"
189 if tool.ToolName() in ChromeTests.SLOW_TOOLS:
190 gtest_filter_files += [os.path.join(gtest_files_dir, name + ".gtest.txt")]
191 for platform_suffix in common.PlatformNames():
192 gtest_filter_files += [
193 os.path.join(gtest_files_dir, name + ".gtest_%s.txt" % platform_suffix),
194 os.path.join(gtest_files_dir, name + ".gtest-%s_%s.txt" % \
195 (tool.ToolName(), platform_suffix))]
196 logging.info("Reading gtest exclude filter files:")
197 for filename in gtest_filter_files:
198 # strip the leading absolute path (may be very long on the bot)
199 # and the following / or \.
200 readable_filename = filename.replace("\\", "/") # '\' on Windows
201 readable_filename = readable_filename.replace(self._source_dir, "")[1:]
202 if not os.path.exists(filename):
203 logging.info(" \"%s\" - not found" % readable_filename)
204 continue
205 logging.info(" \"%s\" - OK" % readable_filename)
206 f = open(filename, 'r')
207 for line in f.readlines():
208 if line.startswith("#") or line.startswith("//") or line.isspace():
209 continue
210 line = line.rstrip()
211 test_prefixes = ["FLAKY", "FAILS"]
212 for p in test_prefixes:
213 # Strip prefixes from the test names.
214 line = line.replace(".%s_" % p, ".")
215 # Exclude the original test name.
216 filters.append(line)
217 if line[-2:] != ".*":
218 # List all possible prefixes if line doesn't end with ".*".
219 for p in test_prefixes:
220 filters.append(line.replace(".", ".%s_" % p))
221 # Get rid of duplicates.
222 filters = set(filters)
223 gtest_filter = self._gtest_filter
224 if len(filters):
225 if gtest_filter:
226 gtest_filter += ":"
227 if gtest_filter.find("-") < 0:
228 gtest_filter += "-"
229 else:
230 gtest_filter = "-"
231 gtest_filter += ":".join(filters)
232 if gtest_filter:
233 cmd.append("--gtest_filter=%s" % gtest_filter)
234
235 @staticmethod
236 def ShowTests():
237 test_to_names = {}
238 for name, test_function in ChromeTests._test_list.iteritems():
239 test_to_names.setdefault(test_function, []).append(name)
240
241 name_to_aliases = {}
242 for names in test_to_names.itervalues():
243 names.sort(key=lambda name: len(name))
244 name_to_aliases[names[0]] = names[1:]
245
246 print
247 print "Available tests:"
248 print "----------------"
249 for name, aliases in sorted(name_to_aliases.iteritems()):
250 if aliases:
251 print " {} (aka {})".format(name, ', '.join(aliases))
252 else:
253 print " {}".format(name)
254
255 def SetupLdPath(self, requires_build_dir):
256 if requires_build_dir:
257 self._EnsureBuildDirFound()
258 elif not self._options.build_dir:
259 return
260
261 # Append build_dir to LD_LIBRARY_PATH so external libraries can be loaded.
262 if (os.getenv("LD_LIBRARY_PATH")):
263 os.putenv("LD_LIBRARY_PATH", "%s:%s" % (os.getenv("LD_LIBRARY_PATH"),
264 self._options.build_dir))
265 else:
266 os.putenv("LD_LIBRARY_PATH", self._options.build_dir)
267
268 def SimpleTest(self, module, name, valgrind_test_args=None, cmd_args=None):
269 tool = valgrind_test.CreateTool(self._options.valgrind_tool)
270 cmd = self._DefaultCommand(tool, name, valgrind_test_args)
271 self._AppendGtestFilter(tool, name, cmd)
272 cmd.extend(['--test-tiny-timeout=1000'])
273 if cmd_args:
274 cmd.extend(cmd_args)
275
276 self.SetupLdPath(True)
277 return tool.Run(cmd, module)
278
279 def RunCmdLine(self):
280 tool = valgrind_test.CreateTool(self._options.valgrind_tool)
281 cmd = self._DefaultCommand(tool, None, self._args)
282 self.SetupLdPath(False)
283 return tool.Run(cmd, None)
284
285 def TestPDFiumUnitTests(self):
286 return self.SimpleTest("pdfium_unittests", "pdfium_unittests")
287
288 def TestPDFiumEmbedderTests(self):
289 return self.SimpleTest("pdfium_embeddertests", "pdfium_embeddertests")
290
291 # The known list of tests.
292 # Recognise the original abbreviations as well as full executable names.
Lei Zhang 2015/11/17 23:33:04 Comment not relevant here.
zhaoqin 2015/11/18 16:26:36 Done.
293 _test_list = {
294 "cmdline" : RunCmdLine,
295 "pdfium_unittests": TestPDFiumUnitTests,
296 "pdfium_embeddertests": TestPDFiumEmbedderTests,
297 }
298
299
300 def _main():
301 parser = optparse.OptionParser("usage: %prog -b <dir> -t <test> "
302 "[-t <test> ...]")
303
304 parser.add_option("--help-tests", dest="help_tests", action="store_true",
305 default=False, help="List all available tests")
306 parser.add_option("-b", "--build-dir",
307 help="the location of the compiler output")
308 parser.add_option("--target", help="Debug or Release")
309 parser.add_option("-t", "--test", action="append", default=[],
310 help="which test to run, supports test:gtest_filter format "
311 "as well.")
312 parser.add_option("--baseline", action="store_true", default=False,
Lei Zhang 2015/11/17 23:33:04 Not used
zhaoqin 2015/11/18 16:26:36 Done.
313 help="generate baseline data instead of validating")
314 parser.add_option("--gtest_filter",
315 help="additional arguments to --gtest_filter")
316 parser.add_option("--gtest_repeat", help="argument for --gtest_repeat")
317 parser.add_option("--gtest_shuffle", action="store_true", default=False,
318 help="Randomize tests' orders on every iteration.")
319 parser.add_option("--gtest_break_on_failure", action="store_true",
320 default=False,
321 help="Drop in to debugger on assertion failure. Also "
322 "useful for forcing tests to exit with a stack dump "
323 "on the first assertion failure when running with "
324 "--gtest_repeat=-1")
325 parser.add_option("-v", "--verbose", action="store_true", default=False,
326 help="verbose output - enable debug log messages")
327 parser.add_option("--tool", dest="valgrind_tool", default="drmemory_full",
328 help="specify a valgrind tool to run the tests under")
329 parser.add_option("--tool_flags", dest="valgrind_tool_flags", default="",
330 help="specify custom flags for the selected valgrind tool")
331 parser.add_option("--keep_logs", action="store_true", default=False,
332 help="store memory tool logs in the <tool>.logs directory "
333 "instead of /tmp.\nThis can be useful for tool "
334 "developers/maintainers.\nPlease note that the <tool>"
335 ".logs directory will be clobbered on tool startup.")
336 parser.add_option("--test-launcher-bot-mode", action="store_true",
337 help="run the tests with --test-launcher-bot-mode")
338 parser.add_option("--test-launcher-total-shards", type=int,
339 help="run the tests with --test-launcher-total-shards")
340 parser.add_option("--test-launcher-shard-index", type=int,
341 help="run the tests with --test-launcher-shard-index")
342
343 options, args = parser.parse_args()
344
345 # Bake target into build_dir.
346 if options.target and options.build_dir:
347 assert (options.target !=
348 os.path.basename(os.path.dirname(options.build_dir)))
349 options.build_dir = os.path.join(os.path.abspath(options.build_dir),
350 options.target)
351
352 if options.verbose:
353 logging_utils.config_root(logging.DEBUG)
354 else:
355 logging_utils.config_root()
356
357 if options.help_tests:
358 ChromeTests.ShowTests()
359 return 0
360
361 if not options.test:
362 parser.error("--test not specified")
363
364 if len(options.test) != 1 and options.gtest_filter:
365 parser.error("--gtest_filter and multiple tests don't make sense together")
366
367 for t in options.test:
368 tests = ChromeTests(options, args, t)
369 ret = tests.Run()
370 if ret: return ret
371 return 0
372
373
374 if __name__ == "__main__":
375 sys.exit(_main())
OLDNEW
« no previous file with comments | « tools/drmemory/scripts/pdfium_tests.bat ('k') | tools/drmemory/scripts/valgrind_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698