Home | History | Annotate | Download | only in testing
      1 #!/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 
      6 """Runs the test with xvfb on linux. Runs the test normally on other platforms.
      7 
      8 For simplicity in gyp targets, this script just runs the test normal on
      9 non-linux platforms.
     10 """
     11 
     12 import os
     13 import platform
     14 import signal
     15 import subprocess
     16 import sys
     17 
     18 import test_env
     19 
     20 
     21 def kill(pid):
     22   """Kills a process and traps exception if the process doesn't exist anymore.
     23   """
     24   # If the process doesn't exist, it raises an exception that we can ignore.
     25   try:
     26     os.kill(pid, signal.SIGKILL)
     27   except OSError:
     28     pass
     29 
     30 
     31 def get_xvfb_path(server_dir):
     32   """Figures out which X server to use."""
     33   xvfb_path = os.path.join(server_dir, 'Xvfb.' + platform.architecture()[0])
     34   if not os.path.exists(xvfb_path):
     35     xvfb_path = os.path.join(server_dir, 'Xvfb')
     36   if not os.path.exists(xvfb_path):
     37     print >> sys.stderr, (
     38         'No Xvfb found in designated server path: %s' % server_dir)
     39     raise Exception('No virtual server')
     40   return xvfb_path
     41 
     42 
     43 def start_xvfb(xvfb_path, display):
     44   """Starts a virtual X server that we run the tests in.
     45 
     46   This makes it so we can run the tests even if we didn't start the tests from
     47   an X session.
     48 
     49   Args:
     50     xvfb_path: Path to Xvfb.
     51   """
     52   cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac']
     53   try:
     54     proc = subprocess.Popen(
     55         cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     56   except OSError:
     57     print >> sys.stderr, 'Failed to run %s' % ' '.join(cmd)
     58     return 0
     59   return proc.pid
     60 
     61 
     62 def wait_for_xvfb(xdisplaycheck, env):
     63   """Waits for xvfb to be fully initialized by using xdisplaycheck."""
     64   try:
     65     subprocess.check_call(
     66         [xdisplaycheck],
     67         stdout=subprocess.PIPE,
     68         stderr=subprocess.STDOUT,
     69         env=env)
     70   except OSError:
     71     print >> sys.stderr, 'Failed to load %s with cwd=%s' % (
     72         xdisplaycheck, os.getcwd())
     73     return False
     74   except subprocess.CalledProcessError:
     75     print >> sys.stderr, (
     76         'Xvfb failed to load properly while trying to run %s' % xdisplaycheck)
     77     return False
     78   return True
     79 
     80 
     81 def run_executable(cmd, build_dir, env):
     82   """Runs an executable within a xvfb buffer on linux or normally on other
     83   platforms.
     84 
     85   Requires that both xvfb and icewm are installed on linux.
     86 
     87   Detects recursion with an environment variable and do not create a recursive X
     88   buffer if present.
     89   """
     90   # First look if we are inside a display.
     91   if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
     92     # No need to recurse.
     93     return test_env.run_executable(cmd, env)
     94 
     95   pid = None
     96   xvfb = 'Xvfb'
     97   try:
     98     if sys.platform == 'linux2':
     99       # Defaults to X display 9.
    100       display = ':9'
    101       pid = start_xvfb(xvfb, display)
    102       if not pid:
    103         return 1
    104       env['DISPLAY'] = display
    105       if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env):
    106         return 3
    107       # Inhibit recursion.
    108       env['_CHROMIUM_INSIDE_XVFB'] = '1'
    109       # Some ChromeOS tests need a window manager. Technically, it could be
    110       # another script but that would be overkill.
    111       try:
    112         ice_cmd = ['icewm']
    113         subprocess.Popen(
    114             ice_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
    115       except OSError:
    116         print >> sys.stderr, 'Failed to run %s' % ' '.join(ice_cmd)
    117         return 1
    118     return test_env.run_executable(cmd, env)
    119   finally:
    120     if pid:
    121       kill(pid)
    122 
    123 
    124 def main():
    125   if len(sys.argv) < 3:
    126     print >> sys.stderr, (
    127         'Usage: xvfb.py [path to build_dir] [command args...]')
    128     return 2
    129   return run_executable(sys.argv[2:], sys.argv[1], os.environ.copy())
    130 
    131 
    132 if __name__ == "__main__":
    133   sys.exit(main())
    134