blob: 1a170cb040ac191135254598c1c0575f2271e4c7 [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
Trent Aptedb1852432018-01-25 02:15:1046def run_executable(cmd, env, stdoutfile=None):
msw11ac9a22015-07-14 23:36:0447 """Runs an executable within Xvfb on Linux or normally on other platforms.
48
Trent Aptedb1852432018-01-25 02:15:1049 If |stdoutfile| is provided, symbolization via script is disabled and stdout
50 is written to this file as well as to stdout.
51
msw11ac9a22015-07-14 23:36:0452 Returns the exit code of the specified commandline, or 1 on failure.
53 """
dpranke7dad4682017-04-26 23:14:5554
55 # It might seem counterintuitive to support a --no-xvfb flag in a script
56 # whose only job is to start xvfb, but doing so allows us to consolidate
57 # the logic in the layers of buildbot scripts so that we *always* use
58 # xvfb by default and don't have to worry about the distinction, it
59 # can remain solely under the control of the test invocation itself.
60 use_xvfb = True
61 if '--no-xvfb' in cmd:
62 use_xvfb = False
63 cmd.remove('--no-xvfb')
64
65 if sys.platform == 'linux2' and use_xvfb:
thomasanderson8c5f7032016-11-28 22:59:1666 if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
67 openbox_proc = None
68 xcompmgr_proc = None
69 try:
70 # Some ChromeOS tests need a window manager.
71 openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE,
72 stderr=subprocess.STDOUT, env=env)
73
74 # Some tests need a compositing wm to make use of transparent visuals.
75 xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE,
76 stderr=subprocess.STDOUT, env=env)
77
Trent Aptedb1852432018-01-25 02:15:1078 return test_env.run_executable(cmd, env, stdoutfile)
thomasanderson8c5f7032016-11-28 22:59:1679 except OSError as e:
80 print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
81 return 1
82 finally:
83 kill(openbox_proc)
84 kill(xcompmgr_proc)
85 else:
86 env['_CHROMIUM_INSIDE_XVFB'] = '1'
jochen0426747e2017-02-09 17:01:1987 xvfb_script = __file__
88 if xvfb_script.endswith('.pyc'):
89 xvfb_script = xvfb_script[:-1]
thomasanderson8c5f7032016-11-28 22:59:1690 return subprocess.call(['xvfb-run', '-a', "--server-args=-screen 0 "
Tom Andersond08c1d042017-12-01 21:40:0191 "1280x800x24 -ac -nolisten tcp -dpi 96 "
92 "+extension RANDR",
jochen0426747e2017-02-09 17:01:1993 xvfb_script] + cmd, env=env)
thomasanderson8c5f7032016-11-28 22:59:1694 else:
Trent Aptedb1852432018-01-25 02:15:1095 return test_env.run_executable(cmd, env, stdoutfile)
[email protected]0a88a652012-03-09 00:34:4596
97
98def main():
dpranke7dad4682017-04-26 23:14:5599 USAGE = 'Usage: xvfb.py [command [--no-xvfb] args...]'
thomasanderson3d074282016-12-06 18:21:12100 if len(sys.argv) < 2:
carloskcac17251a2017-03-15 02:21:07101 print >> sys.stderr, USAGE
[email protected]0a88a652012-03-09 00:34:45102 return 2
carloskcac17251a2017-03-15 02:21:07103
104 # If the user still thinks the first argument is the execution directory then
105 # print a friendly error message and quit.
106 if os.path.isdir(sys.argv[1]):
107 print >> sys.stderr, (
108 'Invalid command: \"%s\" is a directory' % sys.argv[1])
109 print >> sys.stderr, USAGE
110 return 3
111
thomasanderson3d074282016-12-06 18:21:12112 return run_executable(sys.argv[1:], os.environ.copy())
[email protected]0a88a652012-03-09 00:34:45113
114
115if __name__ == "__main__":
116 sys.exit(main())