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

Side by Side Diff: testing/test_env.py

Issue 903273002: Update from https://crrev.com/315085 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: 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 | « testing/platform_test_ios.mm ('k') | third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1 » ('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, executable_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)
133 if executable_path is not None:
134 cmd.append('--executable-path=%s' % executable_path)
114 return cmd 135 return cmd
115 136
116 137
117 def get_json_path(cmd): 138 def get_json_path(cmd):
118 """Extract the JSON test summary path from a command line.""" 139 """Extract the JSON test summary path from a command line."""
119 json_path_flag = '--test-launcher-summary-output=' 140 json_path_flag = '--test-launcher-summary-output='
120 for arg in cmd: 141 for arg in cmd:
121 if arg.startswith(json_path_flag): 142 if arg.startswith(json_path_flag):
122 return arg.split(json_path_flag).pop() 143 return arg.split(json_path_flag).pop()
123 return None 144 return None
124 145
125 146
126 def symbolize_snippets_in_json(cmd, env): 147 def symbolize_snippets_in_json(cmd, env):
127 """Symbolize output snippets inside the JSON test summary.""" 148 """Symbolize output snippets inside the JSON test summary."""
128 json_path = get_json_path(cmd) 149 json_path = get_json_path(cmd)
129 if json_path is None: 150 if json_path is None:
130 return 151 return
131 152
132 try: 153 try:
133 symbolize_command = get_sanitizer_symbolize_command(json_path=json_path) 154 symbolize_command = get_sanitizer_symbolize_command(
155 json_path=json_path, executable_path=cmd[0])
134 p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env) 156 p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env)
135 (_, stderr) = p.communicate() 157 (_, stderr) = p.communicate()
136 except OSError as e: 158 except OSError as e:
137 print 'Exception while symbolizing snippets: %s' % e 159 print 'Exception while symbolizing snippets: %s' % e
138 160
139 if p.returncode != 0: 161 if p.returncode != 0:
140 print "Error: failed to symbolize snippets in JSON:\n" 162 print "Error: failed to symbolize snippets in JSON:\n"
141 print stderr 163 print stderr
142 164
143 165
144 def run_executable(cmd, env): 166 def run_executable(cmd, env):
145 """Runs an executable with: 167 """Runs an executable with:
146 - environment variable CR_SOURCE_ROOT set to the root directory. 168 - environment variable CR_SOURCE_ROOT set to the root directory.
147 - environment variable LANGUAGE to en_US.UTF-8. 169 - environment variable LANGUAGE to en_US.UTF-8.
148 - environment variable CHROME_DEVEL_SANDBOX set 170 - environment variable CHROME_DEVEL_SANDBOX set
149 - Reuses sys.executable automatically. 171 - Reuses sys.executable automatically.
150 """ 172 """
151 extra_env = {} 173 extra_env = {}
152 # Many tests assume a English interface... 174 # Many tests assume a English interface...
153 extra_env['LANG'] = 'en_US.UTF-8' 175 extra_env['LANG'] = 'en_US.UTF-8'
154 # Used by base/base_paths_linux.cc as an override. Just make sure the default 176 # Used by base/base_paths_linux.cc as an override. Just make sure the default
155 # logic is used. 177 # logic is used.
156 env.pop('CR_SOURCE_ROOT', None) 178 env.pop('CR_SOURCE_ROOT', None)
157 extra_env.update(get_sandbox_env(env)) 179 extra_env.update(get_sandbox_env(env))
158 180
159 # Copy logic from tools/build/scripts/slave/runtest.py. 181 # Copy logic from tools/build/scripts/slave/runtest.py.
160 asan = '--asan=1' in cmd 182 asan = '--asan=1' in cmd
161 lsan = '--lsan=1' in cmd 183 lsan = '--lsan=1' in cmd
162 use_symbolization_script = asan and not lsan 184 msan = '--msan=1' in cmd
185 tsan = '--tsan=1' in cmd
186 use_symbolization_script = (asan or msan) and not lsan
163 187
164 if asan: 188 if asan or lsan or msan or tsan:
165 extra_env.update(get_asan_env(cmd, lsan)) 189 extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
166 # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867). 190
167 if sys.platform == 'win32': 191 if lsan or tsan:
168 cmd.append('--no-sandbox') 192 # LSan and TSan are not sandbox-friendly.
169 if lsan:
170 cmd.append('--no-sandbox') 193 cmd.append('--no-sandbox')
171 194
172 cmd = trim_cmd(cmd) 195 cmd = trim_cmd(cmd)
173 196
174 # Ensure paths are correctly separated on windows. 197 # Ensure paths are correctly separated on windows.
175 cmd[0] = cmd[0].replace('/', os.path.sep) 198 cmd[0] = cmd[0].replace('/', os.path.sep)
176 cmd = fix_python_path(cmd) 199 cmd = fix_python_path(cmd)
177 200
178 print('Additional test environment:\n%s\n' 201 print('Additional test environment:\n%s\n'
179 'Command: %s\n' % ( 202 'Command: %s\n' % (
180 '\n'.join(' %s=%s' % 203 '\n'.join(' %s=%s' %
181 (k, v) for k, v in sorted(extra_env.iteritems())), 204 (k, v) for k, v in sorted(extra_env.iteritems())),
182 ' '.join(cmd))) 205 ' '.join(cmd)))
183 env.update(extra_env or {}) 206 env.update(extra_env or {})
184 try: 207 try:
185 # See above comment regarding offline symbolization. 208 # See above comment regarding offline symbolization.
186 if use_symbolization_script: 209 if use_symbolization_script:
187 # Need to pipe to the symbolizer script. 210 # Need to pipe to the symbolizer script.
188 p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, 211 p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
189 stderr=sys.stdout) 212 stderr=sys.stdout)
190 p2 = subprocess.Popen(get_sanitizer_symbolize_command(), 213 p2 = subprocess.Popen(
191 env=env, stdin=p1.stdout) 214 get_sanitizer_symbolize_command(executable_path=cmd[0]),
215 env=env, stdin=p1.stdout)
192 p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. 216 p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
193 p1.wait() 217 p1.wait()
194 p2.wait() 218 p2.wait()
195 # Also feed the out-of-band JSON output to the symbolizer script. 219 # Also feed the out-of-band JSON output to the symbolizer script.
196 symbolize_snippets_in_json(cmd, env) 220 symbolize_snippets_in_json(cmd, env)
197 return p1.returncode 221 return p1.returncode
198 else: 222 else:
199 return subprocess.call(cmd, env=env) 223 return subprocess.call(cmd, env=env)
200 except OSError: 224 except OSError:
201 print >> sys.stderr, 'Failed to start %s' % cmd 225 print >> sys.stderr, 'Failed to start %s' % cmd
202 raise 226 raise
203 227
204 228
205 def main(): 229 def main():
206 return run_executable(sys.argv[1:], os.environ.copy()) 230 return run_executable(sys.argv[1:], os.environ.copy())
207 231
208 232
209 if __name__ == '__main__': 233 if __name__ == '__main__':
210 sys.exit(main()) 234 sys.exit(main())
OLDNEW
« no previous file with comments | « testing/platform_test_ios.mm ('k') | third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1 » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698