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

Side by Side Diff: testing/test_env.py

Issue 895853003: Update from https://crrev.com/314320 (Closed) Base URL: https://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/commit_queue/config.json ('k') | third_party/android_testrunner/OWNERS » ('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
11 import sys 11 import sys
12 12
13 # This is hardcoded to be src/ relative to this script. 13 # This is hardcoded to be src/ relative to this script.
14 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 14 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15 15
16 CHROME_SANDBOX_ENV = 'CHROME_DEVEL_SANDBOX' 16 CHROME_SANDBOX_ENV = 'CHROME_DEVEL_SANDBOX'
17 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox' 17 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox'
18 18
19 19
20 def should_enable_sandbox(cmd, sandbox_path): 20 def get_sandbox_env(env):
21 """Return a boolean indicating that the current slave is capable of using the 21 """Returns the environment flags needed for the SUID sandbox to work."""
22 sandbox and should enable it. This should return True iff the slave is a
23 Linux host with the sandbox file present and configured correctly."""
24 if not (sys.platform.startswith('linux') and
25 os.path.exists(sandbox_path)):
26 return False
27
28 # Copy the check in tools/build/scripts/slave/runtest.py.
29 if '--lsan=1' in cmd:
30 return False
31
32 sandbox_stat = os.stat(sandbox_path)
33 if ((sandbox_stat.st_mode & stat.S_ISUID) and
34 (sandbox_stat.st_mode & stat.S_IRUSR) and
35 (sandbox_stat.st_mode & stat.S_IXUSR) and
36 (sandbox_stat.st_uid == 0)):
37 return True
38 return False
39
40
41 def get_sandbox_env(cmd, env, verbose=False):
42 """Checks enables the sandbox if it is required, otherwise it disables it.
43 Returns the environment flags to set."""
44 extra_env = {} 22 extra_env = {}
45 chrome_sandbox_path = env.get(CHROME_SANDBOX_ENV, CHROME_SANDBOX_PATH) 23 chrome_sandbox_path = env.get(CHROME_SANDBOX_ENV, CHROME_SANDBOX_PATH)
46 24 # The above would silently disable the SUID sandbox if the env value were
47 if should_enable_sandbox(cmd, chrome_sandbox_path): 25 # an empty string. We don't want to allow that. http://crbug.com/245376
48 if verbose: 26 # TODO(jln): Remove this check once it's no longer possible to disable the
49 print 'Enabling sandbox. Setting environment variable:' 27 # sandbox that way.
50 print ' %s="%s"' % (CHROME_SANDBOX_ENV, chrome_sandbox_path) 28 if not chrome_sandbox_path:
51 extra_env[CHROME_SANDBOX_ENV] = chrome_sandbox_path 29 chrome_sandbox_path = CHROME_SANDBOX_PATH
52 else: 30 extra_env[CHROME_SANDBOX_ENV] = chrome_sandbox_path
53 if verbose:
54 print 'Disabling sandbox. Setting environment variable:'
55 print ' CHROME_DEVEL_SANDBOX=""'
56 extra_env['CHROME_DEVEL_SANDBOX'] = ''
57 31
58 return extra_env 32 return extra_env
59 33
60 34
61 def trim_cmd(cmd): 35 def trim_cmd(cmd):
62 """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
63 the host machine to this script running on the swarm slaves.""" 37 the host machine to this script running on the swarm slaves."""
64 internal_flags = frozenset(['--asan=0', '--asan=1', '--lsan=0', '--lsan=1']) 38 internal_flags = frozenset(['--asan=0', '--asan=1', '--lsan=0', '--lsan=1'])
65 return [i for i in cmd if i not in internal_flags] 39 return [i for i in cmd if i not in internal_flags]
66 40
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 if sys.platform == 'darwin': 98 if sys.platform == 'darwin':
125 isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0])) 99 isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
126 # This is needed because the test binary has @executable_path embedded in it 100 # This is needed because the test binary has @executable_path embedded in it
127 # it that the OS tries to resolve to the cache directory and not the mapped 101 # it that the OS tries to resolve to the cache directory and not the mapped
128 # directory. 102 # directory.
129 extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir) 103 extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
130 104
131 return extra_env 105 return extra_env
132 106
133 107
108 def get_sanitizer_symbolize_command(json_path=None):
109 """Construct the command to invoke offline symbolization script."""
110 script_path = '../tools/valgrind/asan/asan_symbolize.py'
111 cmd = [sys.executable, script_path]
112 if json_path is not None:
113 cmd.append('--test-summary-json-file=%s' % json_path)
114 return cmd
115
116
117 def get_json_path(cmd):
118 """Extract the JSON test summary path from a command line."""
119 json_path_flag = '--test-launcher-summary-output='
120 for arg in cmd:
121 if arg.startswith(json_path_flag):
122 return arg.split(json_path_flag).pop()
123 return None
124
125
126 def symbolize_snippets_in_json(cmd, env):
127 """Symbolize output snippets inside the JSON test summary."""
128 json_path = get_json_path(cmd)
129 if json_path is None:
130 return
131
132 try:
133 symbolize_command = get_sanitizer_symbolize_command(json_path=json_path)
134 p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env)
135 (_, stderr) = p.communicate()
136 except OSError as e:
137 print 'Exception while symbolizing snippets: %s' % e
138
139 if p.returncode != 0:
140 print "Error: failed to symbolize snippets in JSON:\n"
141 print stderr
142
143
134 def run_executable(cmd, env): 144 def run_executable(cmd, env):
135 """Runs an executable with: 145 """Runs an executable with:
136 - environment variable CR_SOURCE_ROOT set to the root directory. 146 - environment variable CR_SOURCE_ROOT set to the root directory.
137 - environment variable LANGUAGE to en_US.UTF-8. 147 - environment variable LANGUAGE to en_US.UTF-8.
138 - environment variable CHROME_DEVEL_SANDBOX set if need 148 - environment variable CHROME_DEVEL_SANDBOX set
139 - Reuses sys.executable automatically. 149 - Reuses sys.executable automatically.
140 """ 150 """
141 extra_env = {} 151 extra_env = {}
142 # Many tests assume a English interface... 152 # Many tests assume a English interface...
143 extra_env['LANG'] = 'en_US.UTF-8' 153 extra_env['LANG'] = 'en_US.UTF-8'
144 # Used by base/base_paths_linux.cc as an override. Just make sure the default 154 # Used by base/base_paths_linux.cc as an override. Just make sure the default
145 # logic is used. 155 # logic is used.
146 env.pop('CR_SOURCE_ROOT', None) 156 env.pop('CR_SOURCE_ROOT', None)
147 extra_env.update(get_sandbox_env(cmd, env)) 157 extra_env.update(get_sandbox_env(env))
148 158
149 # Copy logic from tools/build/scripts/slave/runtest.py. 159 # Copy logic from tools/build/scripts/slave/runtest.py.
150 asan = '--asan=1' in cmd 160 asan = '--asan=1' in cmd
151 lsan = '--lsan=1' in cmd 161 lsan = '--lsan=1' in cmd
162 use_symbolization_script = asan and not lsan
152 163
153 if asan: 164 if asan:
154 extra_env.update(get_asan_env(cmd, lsan)) 165 extra_env.update(get_asan_env(cmd, lsan))
166 # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867).
167 if sys.platform == 'win32':
168 cmd.append('--no-sandbox')
155 if lsan: 169 if lsan:
156 cmd.append('--no-sandbox') 170 cmd.append('--no-sandbox')
157 171
158 cmd = trim_cmd(cmd) 172 cmd = trim_cmd(cmd)
159 173
160 # Ensure paths are correctly separated on windows. 174 # Ensure paths are correctly separated on windows.
161 cmd[0] = cmd[0].replace('/', os.path.sep) 175 cmd[0] = cmd[0].replace('/', os.path.sep)
162 cmd = fix_python_path(cmd) 176 cmd = fix_python_path(cmd)
163 177
164 print('Additional test environment:\n%s\n' 178 print('Additional test environment:\n%s\n'
165 'Command: %s\n' % ( 179 'Command: %s\n' % (
166 '\n'.join(' %s=%s' % 180 '\n'.join(' %s=%s' %
167 (k, v) for k, v in sorted(extra_env.iteritems())), 181 (k, v) for k, v in sorted(extra_env.iteritems())),
168 ' '.join(cmd))) 182 ' '.join(cmd)))
169 env.update(extra_env or {}) 183 env.update(extra_env or {})
170 try: 184 try:
171 # See above comment regarding offline symbolization. 185 # See above comment regarding offline symbolization.
172 if asan and not lsan: 186 if use_symbolization_script:
173 # Need to pipe to the symbolizer script. 187 # Need to pipe to the symbolizer script.
174 p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, 188 p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
175 stderr=sys.stdout) 189 stderr=sys.stdout)
176 p2 = subprocess.Popen(["../tools/valgrind/asan/asan_symbolize.py"], 190 p2 = subprocess.Popen(get_sanitizer_symbolize_command(),
177 env=env, stdin=p1.stdout) 191 env=env, stdin=p1.stdout)
178 p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. 192 p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
179 p1.wait() 193 p1.wait()
180 p2.wait() 194 p2.wait()
195 # Also feed the out-of-band JSON output to the symbolizer script.
196 symbolize_snippets_in_json(cmd, env)
181 return p1.returncode 197 return p1.returncode
182 else: 198 else:
183 return subprocess.call(cmd, env=env) 199 return subprocess.call(cmd, env=env)
184 except OSError: 200 except OSError:
185 print >> sys.stderr, 'Failed to start %s' % cmd 201 print >> sys.stderr, 'Failed to start %s' % cmd
186 raise 202 raise
187 203
188 204
189 def main(): 205 def main():
190 return run_executable(sys.argv[1:], os.environ.copy()) 206 return run_executable(sys.argv[1:], os.environ.copy())
191 207
192 208
193 if __name__ == '__main__': 209 if __name__ == '__main__':
194 sys.exit(main()) 210 sys.exit(main())
OLDNEW
« no previous file with comments | « testing/commit_queue/config.json ('k') | third_party/android_testrunner/OWNERS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698