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 |