| OLD | NEW |
| 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 """Runs tests with Xvfb and Openbox on Linux and normally on other platforms.""" | 6 """Runs tests with Xvfb and Openbox on Linux and normally on other platforms.""" |
| 7 | 7 |
| 8 import os | 8 import os |
| 9 import platform | 9 import platform |
| 10 import signal | 10 import signal |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 thread.join(timeout_in_seconds) | 35 thread.join(timeout_in_seconds) |
| 36 if thread.is_alive(): | 36 if thread.is_alive(): |
| 37 print >> sys.stderr, 'Xvfb running after SIGTERM, trying SIGKILL.' | 37 print >> sys.stderr, 'Xvfb running after SIGTERM, trying SIGKILL.' |
| 38 _kill(proc, signal.SIGKILL) | 38 _kill(proc, signal.SIGKILL) |
| 39 | 39 |
| 40 thread.join(timeout_in_seconds) | 40 thread.join(timeout_in_seconds) |
| 41 if thread.is_alive(): | 41 if thread.is_alive(): |
| 42 print >> sys.stderr, 'Xvfb running after SIGTERM and SIGKILL; good luck!' | 42 print >> sys.stderr, 'Xvfb running after SIGTERM and SIGKILL; good luck!' |
| 43 | 43 |
| 44 | 44 |
| 45 def wait_for_xvfb(xdisplaycheck, env): | |
| 46 """Waits for xvfb to be fully initialized by using xdisplaycheck.""" | |
| 47 try: | |
| 48 subprocess.check_output([xdisplaycheck], stderr=subprocess.STDOUT, env=env) | |
| 49 except OSError: | |
| 50 print >> sys.stderr, 'Failed to load %s with cwd=%s' % ( | |
| 51 xdisplaycheck, os.getcwd()) | |
| 52 return False | |
| 53 except subprocess.CalledProcessError as e: | |
| 54 print >> sys.stderr, ('Xvfb failed to load (code %d) according to %s' % | |
| 55 (e.returncode, xdisplaycheck)) | |
| 56 return False | |
| 57 | |
| 58 return True | |
| 59 | |
| 60 | |
| 61 def should_start_xvfb(env): | |
| 62 """Xvfb is only used on Linux and shouldn't be invoked recursively.""" | |
| 63 return sys.platform == 'linux2' and env.get('_CHROMIUM_INSIDE_XVFB') != '1' | |
| 64 | |
| 65 | |
| 66 def start_xvfb(env, build_dir, xvfb_path='Xvfb', display=':9'): | |
| 67 """Start a virtual X server that can run tests without an existing X session. | |
| 68 | |
| 69 Returns the Xvfb and Openbox process Popen objects, or None on failure. | |
| 70 The |env| dictionary is modified to set the DISPLAY and prevent re-entry. | |
| 71 | |
| 72 Args: | |
| 73 env: The os.environ dictionary [copy] to check for re-entry. | |
| 74 build_dir: The path of the build directory, used for xdisplaycheck. | |
| 75 xvfb_path: The path to Xvfb. | |
| 76 display: The X display number to use. | |
| 77 """ | |
| 78 assert should_start_xvfb(env) | |
| 79 assert env.get('_CHROMIUM_INSIDE_XVFB') != '1' | |
| 80 env['_CHROMIUM_INSIDE_XVFB'] = '1' | |
| 81 env['DISPLAY'] = display | |
| 82 xvfb_proc = None | |
| 83 openbox_proc = None | |
| 84 xcompmgr_proc = None | |
| 85 | |
| 86 try: | |
| 87 xvfb_cmd = [xvfb_path, display, '-screen', '0', '1280x800x24', '-ac', | |
| 88 '-nolisten', 'tcp', '-dpi', '96'] | |
| 89 xvfb_proc = subprocess.Popen(xvfb_cmd, stdout=subprocess.PIPE, | |
| 90 stderr=subprocess.STDOUT) | |
| 91 | |
| 92 if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env): | |
| 93 rc = xvfb_proc.poll() | |
| 94 if rc is None: | |
| 95 print 'Xvfb still running after xdisplaycheck failure, stopping.' | |
| 96 kill(xvfb_proc) | |
| 97 else: | |
| 98 print 'Xvfb exited (code %d) after xdisplaycheck failure.' % rc | |
| 99 print 'Xvfb output:' | |
| 100 for l in xvfb_proc.communicate()[0].splitlines(): | |
| 101 print '> %s' % l | |
| 102 return (None, None, None) | |
| 103 | |
| 104 # Some ChromeOS tests need a window manager. | |
| 105 openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE, | |
| 106 stderr=subprocess.STDOUT, env=env) | |
| 107 | |
| 108 # Some tests need a compositing manager to make use of transparent visuals. | |
| 109 xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE, | |
| 110 stderr=subprocess.STDOUT, env=env) | |
| 111 except OSError as e: | |
| 112 print >> sys.stderr, 'Failed to start Xvfb or Openbox or xcompmgr: %s' % \ | |
| 113 str(e) | |
| 114 kill(xvfb_proc) | |
| 115 kill(openbox_proc) | |
| 116 kill(xcompmgr_proc) | |
| 117 return (None, None, None) | |
| 118 | |
| 119 return (xvfb_proc, openbox_proc, xcompmgr_proc) | |
| 120 | |
| 121 | |
| 122 def run_executable(cmd, build_dir, env): | 45 def run_executable(cmd, build_dir, env): |
| 123 """Runs an executable within Xvfb on Linux or normally on other platforms. | 46 """Runs an executable within Xvfb on Linux or normally on other platforms. |
| 124 | 47 |
| 125 Returns the exit code of the specified commandline, or 1 on failure. | 48 Returns the exit code of the specified commandline, or 1 on failure. |
| 126 """ | 49 """ |
| 127 xvfb = None | 50 if sys.platform == 'linux2': |
| 128 openbox = None | 51 if env.get('_CHROMIUM_INSIDE_XVFB') == '1': |
| 129 xcompmgr = None | 52 openbox_proc = None |
| 130 if should_start_xvfb(env): | 53 xcompmgr_proc = None |
| 131 (xvfb, openbox, xcompmgr) = start_xvfb(env, build_dir) | 54 try: |
| 132 if not xvfb or not xvfb.pid or not openbox or not openbox.pid or \ | 55 # Some ChromeOS tests need a window manager. |
| 133 not xcompmgr or not xcompmgr.pid: | 56 openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE, |
| 134 return 1 | 57 stderr=subprocess.STDOUT, env=env) |
| 135 try: | 58 |
| 59 # Some tests need a compositing wm to make use of transparent visuals. |
| 60 xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE, |
| 61 stderr=subprocess.STDOUT, env=env) |
| 62 |
| 63 return test_env.run_executable(cmd, env) |
| 64 except OSError as e: |
| 65 print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e) |
| 66 return 1 |
| 67 finally: |
| 68 kill(openbox_proc) |
| 69 kill(xcompmgr_proc) |
| 70 else: |
| 71 env['_CHROMIUM_INSIDE_XVFB'] = '1' |
| 72 return subprocess.call(['xvfb-run', '-a', "--server-args=-screen 0 " |
| 73 "1280x800x24 -ac -nolisten tcp -dpi 96", |
| 74 __file__, build_dir] + cmd, env=env) |
| 75 else: |
| 136 return test_env.run_executable(cmd, env) | 76 return test_env.run_executable(cmd, env) |
| 137 finally: | |
| 138 kill(xvfb) | |
| 139 kill(openbox) | |
| 140 kill(xcompmgr) | |
| 141 | 77 |
| 142 | 78 |
| 143 def main(): | 79 def main(): |
| 144 if len(sys.argv) < 3: | 80 if len(sys.argv) < 3: |
| 145 print >> sys.stderr, ( | 81 print >> sys.stderr, ( |
| 146 'Usage: xvfb.py [path to build_dir] [command args...]') | 82 'Usage: xvfb.py [path to build_dir] [command args...]') |
| 147 return 2 | 83 return 2 |
| 148 return run_executable(sys.argv[2:], sys.argv[1], os.environ.copy()) | 84 return run_executable(sys.argv[2:], sys.argv[1], os.environ.copy()) |
| 149 | 85 |
| 150 | 86 |
| 151 if __name__ == "__main__": | 87 if __name__ == "__main__": |
| 152 sys.exit(main()) | 88 sys.exit(main()) |
| OLD | NEW |