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

Side by Side Diff: testing/test_env.py

Issue 895923002: Support MSan/TSan in test isolation and test_env.py (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix error Created 5 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
« no previous file with comments | « net/net_unittests.isolate ('k') | ui/app_list/app_list_unittests.isolate » ('j') | 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/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 """Sets environment variables needed to run a chromium unit test.""" 6 """Sets environment variables needed to run a chromium unit test."""
7 7
8 import os 8 import os
9 import stat 9 import stat
10 import subprocess 10 import subprocess
(...skipping 17 matching lines...) Expand all
28 if not chrome_sandbox_path: 28 if not chrome_sandbox_path:
29 chrome_sandbox_path = CHROME_SANDBOX_PATH 29 chrome_sandbox_path = CHROME_SANDBOX_PATH
30 extra_env[CHROME_SANDBOX_ENV] = chrome_sandbox_path 30 extra_env[CHROME_SANDBOX_ENV] = chrome_sandbox_path
31 31
32 return extra_env 32 return extra_env
33 33
34 34
35 def trim_cmd(cmd): 35 def trim_cmd(cmd):
36 """Removes internal flags from cmd since they're just used to communicate from 36 """Removes internal flags from cmd since they're just used to communicate from
37 the host machine to this script running on the swarm slaves.""" 37 the host machine to this script running on the swarm slaves."""
38 internal_flags = frozenset(['--asan=0', '--asan=1', '--lsan=0', '--lsan=1']) 38 sanitizers = ['asan', 'lsan', 'msan', 'tsan']
39 internal_flags = frozenset('--%s=%d' % (name, value)
40 for name in sanitizers
41 for value in [0, 1])
39 return [i for i in cmd if i not in internal_flags] 42 return [i for i in cmd if i not in internal_flags]
40 43
41 44
42 def fix_python_path(cmd): 45 def fix_python_path(cmd):
43 """Returns the fixed command line to call the right python executable.""" 46 """Returns the fixed command line to call the right python executable."""
44 out = cmd[:] 47 out = cmd[:]
45 if out[0] == 'python': 48 if out[0] == 'python':
46 out[0] = sys.executable 49 out[0] = sys.executable
47 elif out[0].endswith('.py'): 50 elif out[0].endswith('.py'):
48 out.insert(0, sys.executable) 51 out.insert(0, sys.executable)
49 return out 52 return out
50 53
51 54
52 def get_asan_env(cmd, lsan): 55 def get_sanitizer_env(cmd, asan, lsan, msan, tsan):
53 """Returns the envirnoment flags needed for ASan and LSan.""" 56 """Returns the envirnoment flags needed for sanitizer tools."""
54 57
55 extra_env = {} 58 extra_env = {}
56 59
57 # Instruct GTK to use malloc while running ASan or LSan tests. 60 # Instruct GTK to use malloc while running sanitizer-instrumented tests.
58 extra_env['G_SLICE'] = 'always-malloc' 61 extra_env['G_SLICE'] = 'always-malloc'
59 62
60 extra_env['NSS_DISABLE_ARENA_FREE_LIST'] = '1' 63 extra_env['NSS_DISABLE_ARENA_FREE_LIST'] = '1'
61 extra_env['NSS_DISABLE_UNLOAD'] = '1' 64 extra_env['NSS_DISABLE_UNLOAD'] = '1'
62 65
63 # TODO(glider): remove the symbolizer path once 66 # TODO(glider): remove the symbolizer path once
64 # https://code.google.com/p/address-sanitizer/issues/detail?id=134 is fixed. 67 # https://code.google.com/p/address-sanitizer/issues/detail?id=134 is fixed.
65 symbolizer_path = os.path.abspath(os.path.join(ROOT_DIR, 'third_party', 68 symbolizer_path = os.path.abspath(os.path.join(ROOT_DIR, 'third_party',
66 'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer')) 69 'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer'))
67 70
68 asan_options = [] 71 if lsan or tsan:
69 if lsan:
70 asan_options.append('detect_leaks=1')
71 if sys.platform == 'linux2':
72 # Use the debug version of libstdc++ under LSan. If we don't, there will
73 # be a lot of incomplete stack traces in the reports.
74 extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
75
76 # LSan is not sandbox-compatible, so we can use online symbolization. In 72 # LSan is not sandbox-compatible, so we can use online symbolization. In
77 # fact, it needs symbolization to be able to apply suppressions. 73 # fact, it needs symbolization to be able to apply suppressions.
78 symbolization_options = ['symbolize=1', 74 symbolization_options = ['symbolize=1',
79 'external_symbolizer_path=%s' % symbolizer_path] 75 'external_symbolizer_path=%s' % symbolizer_path]
80 76 elif asan or msan:
81 suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
82 'suppressions.txt')
83 lsan_options = ['suppressions=%s' % suppressions_file,
84 'print_suppressions=1']
85 extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
86 else:
87 # ASan uses a script for offline symbolization. 77 # ASan uses a script for offline symbolization.
88 # Important note: when running ASan with leak detection enabled, we must use 78 # Important note: when running ASan with leak detection enabled, we must use
89 # the LSan symbolization options above. 79 # the LSan symbolization options above.
90 symbolization_options = ['symbolize=0'] 80 symbolization_options = ['symbolize=0']
91 # Set the path to llvm-symbolizer to be used by asan_symbolize.py 81 # Set the path to llvm-symbolizer to be used by asan_symbolize.py
92 extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path 82 extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path
93 83
94 asan_options.extend(symbolization_options) 84 if asan:
85 asan_options = symbolization_options[:]
86 if lsan:
87 asan_options.append('detect_leaks=1')
95 88
96 extra_env['ASAN_OPTIONS'] = ' '.join(asan_options) 89 extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
97 90
98 if sys.platform == 'darwin': 91 if sys.platform == 'darwin':
99 isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0])) 92 isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
100 # This is needed because the test binary has @executable_path embedded in it 93 # This is needed because the test binary has @executable_path embedded in
101 # it that the OS tries to resolve to the cache directory and not the mapped 94 # it that the OS tries to resolve to the cache directory and not the
102 # directory. 95 # mapped directory.
103 extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir) 96 extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
97
98 if lsan:
99 if asan or msan:
100 lsan_options = []
101 else:
102 lsan_options = symbolization_options[:]
103 if sys.platform == 'linux2':
104 # Use the debug version of libstdc++ under LSan. If we don't, there will
105 # be a lot of incomplete stack traces in the reports.
106 extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
107
108 suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
109 'suppressions.txt')
110 lsan_options += ['suppressions=%s' % suppressions_file,
111 'print_suppressions=1']
112 extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
113
114 if msan:
115 msan_options = symbolization_options[:]
116 if lsan:
117 msan_options.append('detect_leaks=1')
118 extra_env['MSAN_OPTIONS'] = ' '.join(msan_options)
119
120 if tsan:
121 tsan_options = symbolization_options[:]
122 extra_env['TSAN_OPTIONS'] = ' '.join(tsan_options)
104 123
105 return extra_env 124 return extra_env
106 125
107 126
108 def get_sanitizer_symbolize_command(json_path=None): 127 def get_sanitizer_symbolize_command(json_path=None):
109 """Construct the command to invoke offline symbolization script.""" 128 """Construct the command to invoke offline symbolization script."""
110 script_path = '../tools/valgrind/asan/asan_symbolize.py' 129 script_path = '../tools/valgrind/asan/asan_symbolize.py'
111 cmd = [sys.executable, script_path] 130 cmd = [sys.executable, script_path]
112 if json_path is not None: 131 if json_path is not None:
113 cmd.append('--test-summary-json-file=%s' % json_path) 132 cmd.append('--test-summary-json-file=%s' % json_path)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 # Many tests assume a English interface... 171 # Many tests assume a English interface...
153 extra_env['LANG'] = 'en_US.UTF-8' 172 extra_env['LANG'] = 'en_US.UTF-8'
154 # Used by base/base_paths_linux.cc as an override. Just make sure the default 173 # Used by base/base_paths_linux.cc as an override. Just make sure the default
155 # logic is used. 174 # logic is used.
156 env.pop('CR_SOURCE_ROOT', None) 175 env.pop('CR_SOURCE_ROOT', None)
157 extra_env.update(get_sandbox_env(env)) 176 extra_env.update(get_sandbox_env(env))
158 177
159 # Copy logic from tools/build/scripts/slave/runtest.py. 178 # Copy logic from tools/build/scripts/slave/runtest.py.
160 asan = '--asan=1' in cmd 179 asan = '--asan=1' in cmd
161 lsan = '--lsan=1' in cmd 180 lsan = '--lsan=1' in cmd
162 use_symbolization_script = asan and not lsan 181 msan = '--msan=1' in cmd
182 tsan = '--tsan=1' in cmd
183 use_symbolization_script = (asan or msan) and not lsan
163 184
164 if asan: 185 if asan or lsan or msan or tsan:
165 extra_env.update(get_asan_env(cmd, lsan)) 186 extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
166 # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867). 187
167 if sys.platform == 'win32': 188 if lsan or tsan or (asan and sys.platform == 'win32'):
189 # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867).
190 # LSan and TSan are not sandbox-friendly.
168 cmd.append('--no-sandbox') 191 cmd.append('--no-sandbox')
169 if lsan:
170 cmd.append('--no-sandbox')
171 192
172 cmd = trim_cmd(cmd) 193 cmd = trim_cmd(cmd)
173 194
174 # Ensure paths are correctly separated on windows. 195 # Ensure paths are correctly separated on windows.
175 cmd[0] = cmd[0].replace('/', os.path.sep) 196 cmd[0] = cmd[0].replace('/', os.path.sep)
176 cmd = fix_python_path(cmd) 197 cmd = fix_python_path(cmd)
177 198
178 print('Additional test environment:\n%s\n' 199 print('Additional test environment:\n%s\n'
179 'Command: %s\n' % ( 200 'Command: %s\n' % (
180 '\n'.join(' %s=%s' % 201 '\n'.join(' %s=%s' %
(...skipping 20 matching lines...) Expand all
201 print >> sys.stderr, 'Failed to start %s' % cmd 222 print >> sys.stderr, 'Failed to start %s' % cmd
202 raise 223 raise
203 224
204 225
205 def main(): 226 def main():
206 return run_executable(sys.argv[1:], os.environ.copy()) 227 return run_executable(sys.argv[1:], os.environ.copy())
207 228
208 229
209 if __name__ == '__main__': 230 if __name__ == '__main__':
210 sys.exit(main()) 231 sys.exit(main())
OLDNEW
« no previous file with comments | « net/net_unittests.isolate ('k') | ui/app_list/app_list_unittests.isolate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698