blob: e51d3c48f507453de9288546eb4b68a183e44cc3 [file] [log] [blame]
[email protected]0a88a652012-03-09 00:34:451#!/usr/bin/env python
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
4# found in the LICENSE file.
5
msw11ac9a22015-07-14 23:36:046"""Runs tests with Xvfb and Openbox on Linux and normally on other platforms."""
[email protected]0a88a652012-03-09 00:34:457
8import os
carloskcac17251a2017-03-15 02:21:079import os.path
[email protected]0a88a652012-03-09 00:34:4510import platform
11import signal
12import subprocess
13import sys
msw76cf5fe12015-07-16 23:48:5714import threading
[email protected]0a88a652012-03-09 00:34:4515
16import test_env
17
18
msw76cf5fe12015-07-16 23:48:5719def _kill(proc, send_signal):
msw11ac9a22015-07-14 23:36:0420 """Kills |proc| and ignores exceptions thrown for non-existent processes."""
[email protected]0a88a652012-03-09 00:34:4521 try:
msw76cf5fe12015-07-16 23:48:5722 os.kill(proc.pid, send_signal)
[email protected]0a88a652012-03-09 00:34:4523 except OSError:
24 pass
25
26
msw76cf5fe12015-07-16 23:48:5727def kill(proc, timeout_in_seconds=10):
28 """Tries to kill |proc| gracefully with a timeout for each signal."""
29 if not proc or not proc.pid:
30 return
31
32 _kill(proc, signal.SIGTERM)
33 thread = threading.Thread(target=proc.wait)
34 thread.start()
35
36 thread.join(timeout_in_seconds)
37 if thread.is_alive():
38 print >> sys.stderr, 'Xvfb running after SIGTERM, trying SIGKILL.'
39 _kill(proc, signal.SIGKILL)
40
41 thread.join(timeout_in_seconds)
42 if thread.is_alive():
43 print >> sys.stderr, 'Xvfb running after SIGTERM and SIGKILL; good luck!'
44
45
thomasanderson3d074282016-12-06 18:21:1246def run_executable(cmd, env):
msw11ac9a22015-07-14 23:36:0447 """Runs an executable within Xvfb on Linux or normally on other platforms.
48
49 Returns the exit code of the specified commandline, or 1 on failure.
50 """
dpranke7dad4682017-04-26 23:14:5551
52 # It might seem counterintuitive to support a --no-xvfb flag in a script
53 # whose only job is to start xvfb, but doing so allows us to consolidate
54 # the logic in the layers of buildbot scripts so that we *always* use
55 # xvfb by default and don't have to worry about the distinction, it
56 # can remain solely under the control of the test invocation itself.
57 use_xvfb = True
58 if '--no-xvfb' in cmd:
59 use_xvfb = False
60 cmd.remove('--no-xvfb')
61
62 if sys.platform == 'linux2' and use_xvfb:
thomasanderson8c5f7032016-11-28 22:59:1663 if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
64 openbox_proc = None
65 xcompmgr_proc = None
66 try:
67 # Some ChromeOS tests need a window manager.
68 openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE,
69 stderr=subprocess.STDOUT, env=env)
70
71 # Some tests need a compositing wm to make use of transparent visuals.
72 xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE,
73 stderr=subprocess.STDOUT, env=env)
74
75 return test_env.run_executable(cmd, env)
76 except OSError as e:
77 print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
78 return 1
79 finally:
80 kill(openbox_proc)
81 kill(xcompmgr_proc)
82 else:
83 env['_CHROMIUM_INSIDE_XVFB'] = '1'
jochen0426747e2017-02-09 17:01:1984 xvfb_script = __file__
85 if xvfb_script.endswith('.pyc'):
86 xvfb_script = xvfb_script[:-1]
thomasanderson8c5f7032016-11-28 22:59:1687 return subprocess.call(['xvfb-run', '-a', "--server-args=-screen 0 "
88 "1280x800x24 -ac -nolisten tcp -dpi 96",
jochen0426747e2017-02-09 17:01:1989 xvfb_script] + cmd, env=env)
thomasanderson8c5f7032016-11-28 22:59:1690 else:
[email protected]0a88a652012-03-09 00:34:4591 return test_env.run_executable(cmd, env)
[email protected]0a88a652012-03-09 00:34:4592
93
94def main():
dpranke7dad4682017-04-26 23:14:5595 USAGE = 'Usage: xvfb.py [command [--no-xvfb] args...]'
thomasanderson3d074282016-12-06 18:21:1296 if len(sys.argv) < 2:
carloskcac17251a2017-03-15 02:21:0797 print >> sys.stderr, USAGE
[email protected]0a88a652012-03-09 00:34:4598 return 2
carloskcac17251a2017-03-15 02:21:0799
100 # If the user still thinks the first argument is the execution directory then
101 # print a friendly error message and quit.
102 if os.path.isdir(sys.argv[1]):
103 print >> sys.stderr, (
104 'Invalid command: \"%s\" is a directory' % sys.argv[1])
105 print >> sys.stderr, USAGE
106 return 3
107
thomasanderson3d074282016-12-06 18:21:12108 return run_executable(sys.argv[1:], os.environ.copy())
[email protected]0a88a652012-03-09 00:34:45109
110
111if __name__ == "__main__":
112 sys.exit(main())