#!/usr/bin/env vpython3
# Copyright 2012 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Runs tests with Xvfb/Xorg and Openbox/Weston/Mutter on Linux and normally on
other platforms."""

from __future__ import print_function

import copy
import os
import os.path
import random
import re
import signal
import socket
import subprocess
import sys
import tempfile
import threading
import time
import uuid

from contextlib import contextmanager

# vpython-provided modules.
import psutil  # pylint: disable=import-error

# //testing imports.
import test_env

DEFAULT_XVFB_WHD = '1280x800x24'
DEFAULT_MUTTER_DISPLAY = '1920x1200'

# pylint: disable=useless-object-inheritance


class _ProcessError(Exception):
  """Exception raised when the requested display server or compositor cannot
  start."""


def kill(proc, name, timeout_in_seconds=10):
  """Tries to kill |proc| gracefully with a timeout for each signal."""
  if not proc:
    return

  thread = threading.Thread(target=proc.wait)
  try:
    proc.terminate()
    thread.start()

    thread.join(timeout_in_seconds)
    if thread.is_alive():
      print('%s running after SIGTERM, trying SIGKILL.\n' % name,
            file=sys.stderr)
      proc.kill()
  except OSError as e:
    # proc.terminate()/kill() can raise, not sure if only ProcessLookupError
    # which is explained in https://bugs.python.org/issue40550#msg382427
    print('Exception while killing process %s: %s' % (name, e), file=sys.stderr)

  thread.join(timeout_in_seconds)
  if thread.is_alive():
    print('%s running after SIGTERM and SIGKILL; good luck!\n' % name,
          file=sys.stderr)


@contextmanager
def dbus_session(env):  # pylint: disable=inconsistent-return-statements
  """Starts a DBus session.

  Works around a bug in GLib where it performs operations which aren't
  async-signal-safe (in particular, memory allocations) between fork and exec
  when it spawns subprocesses. This causes threads inside Chrome's browser and
  utility processes to get stuck, and this harness to hang waiting for those
  processes, which will never terminate. This doesn't happen on users'
  machines, because they have an active desktop session and the
  DBUS_SESSION_BUS_ADDRESS environment variable set, but it can happen on
  headless environments. This is fixed by glib commit [1], but this workaround
  will be necessary until the fix rolls into Chromium's CI.

  [1] f2917459f745bebf931bccd5cc2c33aa81ef4d12

  Modifies the passed in environment with at least DBUS_SESSION_BUS_ADDRESS and
  DBUS_SESSION_BUS_PID set.

  Returns the pid of the dbus-daemon if started, or None otherwise.
  """
  dbus_pid = None
  try:
    if 'DBUS_SESSION_BUS_ADDRESS' not in os.environ:
      dbus_output = subprocess.check_output(['dbus-launch'],
                                            env=env).decode('utf-8').split('\n')
      for line in dbus_output:
        m = re.match(r'([^=]+)\=(.+)', line)
        if m:
          env[m.group(1)] = m.group(2)
      dbus_pid = int(env['DBUS_SESSION_BUS_PID'])
  except (subprocess.CalledProcessError, OSError, KeyError, ValueError) as e:
    print('Exception while running dbus_launch: %s' % e)
  try:
    yield
  finally:
    # dbus-daemon is not a subprocess, so we can't SIGTERM+waitpid() on it.
    # To ensure it exits, use SIGKILL which should be safe since all other
    # processes that it would have been servicing have exited.
    if dbus_pid:
      os.kill(dbus_pid, signal.SIGKILL)


# TODO(crbug.com/40621504): Encourage setting flags to False.
def run_executable(cmd,
                   env,
                   stdoutfile=None,
                   use_openbox=True,
                   use_xcompmgr=True,
                   xvfb_whd=None,
                   cwd=None):
  """Runs an executable within Weston, Xvfb or Xorg on Linux or normally on
     other platforms.

  The method sets SIGUSR1 handler for Xvfb to return SIGUSR1
  when it is ready for connections.
  https://www.x.org/archive/X11R7.5/doc/man/man1/Xserver.1.html under Signals.

  Args:
    cmd: Command to be executed.
    env: A copy of environment variables. "DISPLAY" and will be set if Xvfb is
      used. "WAYLAND_DISPLAY" will be set if Weston is used.
    stdoutfile: If provided, symbolization via script is disabled and stdout
      is written to this file as well as to stdout.
    use_openbox: A flag to use openbox process.
      Some ChromeOS tests need a window manager.
    use_xcompmgr: A flag to use xcompmgr process.
      Some tests need a compositing wm to make use of transparent visuals.
    xvfb_whd: WxHxD to pass to xvfb or DEFAULT_XVFB_WHD if None
    cwd: Current working directory.

  Returns:
    the exit code of the specified commandline, or 1 on failure.
  """

  # It might seem counterintuitive to support a --no-xvfb flag in a script
  # whose only job is to start xvfb, but doing so allows us to consolidate
  # the logic in the layers of buildbot scripts so that we *always* use
  # this script by default and don't have to worry about the distinction, it
  # can remain solely under the control of the test invocation itself.
  # Historically, this flag turned off xvfb, but now turns off both X11 backings
  # (xvfb/Xorg). As of crrev.com/c/5631242, Xorg became the default backing when
  # no flags are supplied. Xorg is mostly a drop in replacement to Xvfb but has
  # better support for dummy drivers and multi-screen testing (See:
  # crbug.com/40257169 and http://tinyurl.com/4phsuupf). Requires Xorg binaries
  # (package: xserver-xorg-core)
  use_xvfb = False
  use_xorg = True

  if '--no-xvfb' in cmd:
    use_xvfb = False
    use_xorg = False  # Backwards compatibly turns off all X11 backings.
    cmd.remove('--no-xvfb')

  # Support forcing legacy xvfb backing.
  if '--use-xvfb' in cmd:
    if not use_xorg and not use_xvfb:
      print('Conflicting flags --use-xvfb and --no-xvfb\n', file=sys.stderr)
      return 1
    use_xvfb = True
    use_xorg = False
    cmd.remove('--use-xvfb')

  # Tests that run on Linux platforms with Ozone/Wayland backend require
  # a Weston instance. However, it is also required to disable xvfb so
  # that Weston can run in a pure headless environment.
  use_weston = False
  if '--use-weston' in cmd:
    if use_xvfb or use_xorg:
      print('Unable to use Weston with xvfb or Xorg.\n', file=sys.stderr)
      return 1
    use_weston = True
    cmd.remove('--use-weston')

  use_mutter = False
  mutter_display = DEFAULT_MUTTER_DISPLAY
  if '--use-mutter' in cmd:
    if use_xvfb or use_xorg or use_weston:
      print('Unable to use mutter with xvfb or Xorg or weston.\n',
            file=sys.stderr)
      return 1
    use_mutter = True
    cmd.remove('--use-mutter')
    for arg in cmd:
      if arg.startswith('--mutter-display='):
        mutter_display = arg.split('=')[1]
        cmd.remove(arg)
        break


  if sys.platform.startswith('linux') and (use_xvfb or use_xorg):
    return _run_with_x11(cmd, env, stdoutfile, use_openbox, use_xcompmgr,
                         use_xorg, xvfb_whd or DEFAULT_XVFB_WHD, cwd)
  if use_weston:
    return _run_with_weston(cmd, env, stdoutfile, cwd)

  if use_mutter:
    return _run_with_mutter(cmd, env, stdoutfile, cwd, mutter_display)

  return test_env.run_executable(cmd, env, stdoutfile, cwd)


def _re_search_command(regex, args, **kwargs):
  """Runs a subprocess defined by `args` and returns a regex match for the
  given expression on the output."""
  return re.search(
      regex,
      subprocess.check_output(args,
                              stderr=subprocess.STDOUT,
                              text=True,
                              **kwargs), re.IGNORECASE)


def _make_xorg_modeline(width, height, refresh):
  """Generates a tuple of a modeline (list of parameters) and label based off a
  specified width, height and refresh rate.
  See: https://www.x.org/archive/X11R7.0/doc/html/chips4.html"""
  re_matches = _re_search_command(
      r'Modeline "(.*)"\s+(.*)',
      ['cvt', str(width), str(height),
       str(refresh)],
  )
  modeline_label = re_matches.group(1)
  modeline = re_matches.group(2)
  # Split the modeline string on spaces, and filter out empty element (cvt adds
  # double spaces between in some parts).
  return (modeline_label, list(filter(lambda a: a != '', modeline.split(' '))))


def _get_supported_virtual_sizes(default_whd):
  """Returns a list of tuples (width, height) for supported monitor resolutions.
  The list will always include the default size defined in `default_whd`"""
  # Note: 4K resolution 3840x2160 doesn't seem to be supported and the mode
  # silently gets dropped which makes subsequent calls to xrandr --addmode fail.
  (default_width, default_height, _) = default_whd.split('x')
  default_size = (int(default_width), int(default_height))
  return sorted(
      set([default_size, (800, 600), (1024, 768), (1920, 1080), (1600, 1200)]))


def _make_xorg_config(default_whd):
  """Generates an Xorg config file and returns the file path. See:
  https://www.x.org/releases/current/doc/man/man5/xorg.conf.5.xhtml"""
  (_, _, depth) = default_whd.split('x')
  mode_sizes = _get_supported_virtual_sizes(default_whd)
  modelines = []
  mode_labels = []
  for width, height in mode_sizes:
    (modeline_label, modeline) = _make_xorg_modeline(width, height, 60)
    modelines.append('Modeline "%s" %s' % (modeline_label, ' '.join(modeline)))
    mode_labels.append('"%s"' % modeline_label)
  config = """
Section "Monitor"
  Identifier "Monitor0"
  HorizSync 5.0 - 1000.0
  VertRefresh 5.0 - 200.0
  %s
EndSection
Section "Device"
  Identifier "Device0"
  # Dummy driver requires package `xserver-xorg-video-dummy`.
  Driver "dummy"
  VideoRam 256000
EndSection
Section "Screen"
  Identifier "Screen0"
  Device "Device0"
  Monitor "Monitor0"
  SubSection "Display"
    Depth %s
    Modes %s
  EndSubSection
EndSection
  """ % ('\n'.join(modelines), depth, ' '.join(mode_labels))
  config_file = os.path.join(tempfile.gettempdir(),
                             'xorg-%s.config' % uuid.uuid4().hex)
  with open(config_file, 'w') as f:
    f.write(config)
  return config_file

def _setup_xrandr(env, default_whd):
  """Configures xrandr display(s)"""

  # Calls xrandr with the provided argument array
  def call_xrandr(args):
    subprocess.check_call(['xrandr'] + args,
                          env=env,
                          stdout=subprocess.DEVNULL,
                          stderr=subprocess.STDOUT)

  (default_width, default_height, _) = default_whd.split('x')
  default_size = (int(default_width), int(default_height))

  # The minimum version of xserver-xorg-video-dummy is 0.4.0-1 which adds
  # XRANDR support. Older versions will be missing the "DUMMY" outputs.
  # Reliably checking the version is difficult, so check if the xrandr output
  # includes the DUMMY displays before trying to configure them.
  dummy_displays_available = _re_search_command('DUMMY[0-9]', ['xrandr', '-q'],
                                                env=env)
  if dummy_displays_available:
    screen_sizes = _get_supported_virtual_sizes(default_whd)
    output_names = ['DUMMY0', 'DUMMY1', 'DUMMY2', 'DUMMY3', 'DUMMY4']
    refresh_rate = 60
    for width, height in screen_sizes:
      (modeline_label, _) = _make_xorg_modeline(width, height, 60)
      for output_name in output_names:
        call_xrandr(['--addmode', output_name, modeline_label])
    (default_mode_label, _) = _make_xorg_modeline(*default_size, refresh_rate)
    # Set the mode of all monitors to connect and activate them.
    for i, name in enumerate(output_names):
      args = ['--output', name, '--mode', default_mode_label]
      if i > 0:
        args += ['--right-of', output_names[i - 1]]
      call_xrandr(args)

  # Sets the primary monitor to the default size and marks the rest as disabled.
  call_xrandr(['-s', '%dx%d' % default_size])
  # Set the DPI to something realistic (as required by some desktops).
  call_xrandr(['--dpi', '96'])


def _setup_signals():
  signal.signal(signal.SIGTERM, raise_process_terminated)
  signal.signal(signal.SIGINT, raise_process_terminated)


def _run_with_x11(cmd, env, stdoutfile, use_openbox, use_xcompmgr, use_xorg,
                  xvfb_whd, cwd):
  """Runs with an X11 server. Uses Xvfb by default and Xorg when use_xorg is
  True."""
  openbox_proc = None
  openbox_ready = MutableBoolean()

  def set_openbox_ready(*_):
    openbox_ready.setvalue(True)

  xcompmgr_proc = None
  x11_proc = None
  x11_ready = MutableBoolean()

  def set_x11_ready(*_):
    x11_ready.setvalue(True)

  x11_binary = 'Xorg' if use_xorg else 'Xvfb'
  xorg_config_file = _make_xorg_config(xvfb_whd) if use_xorg else None

  if 'XDG_CURRENT_DESKTOP' in env:
    del env['XDG_CURRENT_DESKTOP']

  with dbus_session(env):
    try:
      _setup_signals()

      # Due to race condition for display number, Xvfb/Xorg might fail to run.
      # If it does fail, try again up to 10 times, similarly to xvfb-run.
      for _ in range(10):
        x11_ready.setvalue(False)
        display = find_display()

        x11_cmd = None
        if use_xorg:
          x11_cmd = ['Xorg', display, '-noreset', '-config', xorg_config_file]
        else:
          x11_cmd = [
              'Xvfb', display, '-screen', '0', xvfb_whd, '-ac', '-nolisten',
              'tcp', '-dpi', '96', '+extension', 'RANDR', '-maxclients', '512'
          ]

        # Sets SIGUSR1 to ignore for Xvfb/Xorg to signal current process
        # when it is ready. Due to race condition, USR1 signal could be sent
        # before the process resets the signal handler, we cannot rely on
        # signal handler to change on time.
        signal.signal(signal.SIGUSR1, signal.SIG_IGN)
        x11_proc = subprocess.Popen(x11_cmd, stderr=subprocess.STDOUT, env=env)
        signal.signal(signal.SIGUSR1, set_x11_ready)
        for _ in range(30):
          time.sleep(.1)  # gives Xvfb/Xorg time to start or fail.
          if x11_ready.getvalue() or x11_proc.poll() is not None:
            break  # xvfb/xorg sent ready signal, or already failed and stopped.

        if x11_proc.poll() is None:
          if x11_ready.getvalue():
            break  # xvfb/xorg is ready
          kill(x11_proc, x11_binary)  # still not ready, give up and retry

      if x11_proc.poll() is not None:
        raise _ProcessError('Failed to start after 10 tries')

      env['DISPLAY'] = display
      # Set dummy variable for scripts.
      env['XVFB_DISPLAY'] = display

      if use_openbox:
        # Openbox will send a SIGUSR1 signal to the current process notifying
        # the script it has started up.
        current_proc_id = os.getpid()

        # The CMD that is passed via the --startup flag.
        openbox_startup_cmd = 'kill --signal SIGUSR1 %s' % str(current_proc_id)
        # Setup the signal handlers before starting the openbox instance.
        signal.signal(signal.SIGUSR1, signal.SIG_IGN)
        signal.signal(signal.SIGUSR1, set_openbox_ready)
        # Retry up to 10 times due to flaky fails (crbug.com/349187865)
        for _ in range(10):
          openbox_ready.setvalue(False)
          openbox_proc = subprocess.Popen(
              ['openbox', '--sm-disable', '--startup', openbox_startup_cmd],
              stderr=subprocess.STDOUT,
              env=env)
          for _ in range(30):
            time.sleep(.1)  # gives Openbox time to start or fail.
            if openbox_ready.getvalue() or openbox_proc.poll() is not None:
              break  # openbox sent ready signal, or failed and stopped.

          if openbox_proc.poll() is None:
            if openbox_ready.getvalue():
              break  # openbox is ready
            kill(openbox_proc, 'openbox')  # still not ready, give up and retry
            print('Openbox failed to start. Retrying.', file=sys.stderr)

        if openbox_proc.poll() is not None:
          raise _ProcessError('Failed to start openbox after 10 tries')

      if use_xcompmgr:
        xcompmgr_proc = subprocess.Popen('xcompmgr',
                                         stderr=subprocess.STDOUT,
                                         env=env)

      if use_xorg:
        _setup_xrandr(env, xvfb_whd)

      return test_env.run_executable(cmd, env, stdoutfile, cwd)
    except OSError as e:
      print('Failed to start %s or Openbox: %s\n' % (x11_binary, str(e)),
            file=sys.stderr)
      return 1
    except _ProcessError as e:
      print('%s fail: %s\n' % (x11_binary, str(e)), file=sys.stderr)
      return 1
    finally:
      kill(openbox_proc, 'openbox')
      kill(xcompmgr_proc, 'xcompmgr')
      kill(x11_proc, x11_binary)
      if xorg_config_file is not None:
        os.remove(xorg_config_file)


def _run_with_wayland_common(compositor_executable, cmd, env):
  _setup_signals()

  # It's easiest to run compositor from the build directory, as then we don't
  # need to specify the paths of the backend's and modules' .so files.
  if not os.path.isfile(compositor_executable):
    # If this script isn't run from the build directory, try deducing it from
    # the test executable's path and change to it.
    build_dir = os.path.dirname(cmd[0])
    if os.path.isdir(build_dir):
      os.chdir(build_dir)
      # Strip build directory from the test executable's path.
      cmd[0] = os.path.join('.', os.path.basename(cmd[0]))

  # The bundled compositor (//third_party/compositor) is used by Linux Ozone
  # Wayland CI and CQ testers and compiled by //ui/ozone/platform/wayland
  # whenever there is a dependency on the Ozone/Wayland and
  # use_bundled_compositor is set in gn args. However, some tests do not require
  # Wayland or do not use //ui/ozone at all, but still have --use-compositor
  # flag set by the OZONE_WAYLAND variant (see //testing/buildbot/variants.pyl).
  # This results in failures and those tests cannot be run because of the
  # exception that informs about missing compositor binary. Thus, to overcome
  # the issue before a better solution is found, add a check for the
  # "compositor" binary here and run tests without Wayland compositor if the
  # compositor binary is not found.
  # TODO(https://crbug.com/40169257): find a better solution.
  if not os.path.isfile(compositor_executable):
    print('Compositor is not available. Starting without Wayland compositor')
    return (False, cmd)

  # Set $XDG_RUNTIME_DIR if it is not set.
  _set_xdg_runtime_dir(env)

  return (True, cmd)


# TODO(crbug.com/40122046): Write tests.
def _run_with_weston(cmd, env, stdoutfile, cwd):
  with dbus_session(env):
    weston_proc = None

    try:
      weston_executable = './weston'
      compositor_found, cmd = _run_with_wayland_common(weston_executable, cmd,
                                                       env)
      if not compositor_found:
        return test_env.run_executable(cmd, env, stdoutfile, cwd)

      # Write options that can't be passed via CLI flags to the config file.
      # 1) panel-position=none - disables the panel, which might interfere with
      # the tests by blocking mouse input.
      with open(_weston_config_file_path(), 'w') as weston_config_file:
        weston_config_file.write('[shell]\npanel-position=none')

      # Weston is compiled along with the Ozone/Wayland platform, and is
      # fetched as data deps. Thus, run it from the current directory.
      #
      # Weston is used with the following flags:
      # 1) --backend=headless-backend.so - runs Weston in a headless mode
      # that does not require a real GPU card.
      # 2) --idle-time=0 - disables idle timeout, which prevents Weston
      # to enter idle state. Otherwise, Weston stops to send frame callbacks,
      # and tests start to time out (this typically happens after 300 seconds -
      # the default time after which Weston enters the idle state).
      # 3) --modules=ui-controls.so,systemd-notify.so - enables support for the
      # ui-controls Wayland protocol extension and the systemd-notify protocol.
      # 4) --width && --height set size of a virtual display: we need to set
      # an adequate size so that tests can have more room for managing size
      # of windows.
      # 5) --config=... - tells Weston to use our custom config.
      weston_cmd = [
          weston_executable, '--backend=headless-backend.so', '--idle-time=0',
          '--modules=ui-controls.so,systemd-notify.so', '--width=1280',
          '--height=800', '--config=' + _weston_config_file_path()
      ]

      if '--weston-use-gl' in cmd:
        # Runs Weston using hardware acceleration instead of SwiftShader.
        weston_cmd.append('--use-gl')
        cmd.remove('--weston-use-gl')

      if '--weston-debug-logging' in cmd:
        cmd.remove('--weston-debug-logging')
        env = copy.deepcopy(env)
        env['WAYLAND_DEBUG'] = '1'

      # We use the systemd-notify protocol to detect whether weston has launched
      # successfully. We listen on a unix socket and set the NOTIFY_SOCKET
      # environment variable to the socket's path. If we tell it to load its
      # systemd-notify module, weston will send a 'READY=1' message to the
      # socket once it has loaded that module.  See the sd_notify(3) man page
      # and weston's compositor/systemd-notify.c for more details.
      with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM
                         | socket.SOCK_NONBLOCK) as notify_socket:
        notify_socket.bind(_weston_notify_socket_address())
        env['NOTIFY_SOCKET'] = _weston_notify_socket_address()

        weston_proc_display = None
        for _ in range(10):
          weston_proc = subprocess.Popen(weston_cmd,
                                         stderr=subprocess.STDOUT,
                                         env=env)

          for _ in range(25):
            time.sleep(0.1)  # Gives weston some time to start.
            try:
              if notify_socket.recv(512) == b'READY=1':
                break
            except BlockingIOError:
              continue

          for _ in range(25):
            # The 'READY=1' message is sent as soon as weston loads the
            # systemd-notify module. This happens shortly before spawning its
            # subprocesses (e.g. desktop-shell). Wait some more to ensure they
            # have been spawned.
            time.sleep(0.1)

            # Get the $WAYLAND_DISPLAY set by Weston and pass it to the test
            # launcher. Please note that this env variable is local for the
            # process. That's the reason we have to read it from Weston
            # separately.
            weston_proc_display = _get_display_from_weston(weston_proc.pid)
            if weston_proc_display is not None:
              break  # Weston could launch and we found the display.

          # Also break from the outer loop.
          if weston_proc_display is not None:
            break

      # If we couldn't find the display after 10 tries, raise an exception.
      if weston_proc_display is None:
        raise _ProcessError('Failed to start Weston.')

      env.pop('NOTIFY_SOCKET')

      env['WAYLAND_DISPLAY'] = weston_proc_display
      if '--chrome-wayland-debugging' in cmd:
        cmd.remove('--chrome-wayland-debugging')
        env['WAYLAND_DEBUG'] = '1'
      else:
        env['WAYLAND_DEBUG'] = '0'

      return test_env.run_executable(cmd, env, stdoutfile, cwd)
    except OSError as e:
      print('Failed to start Weston: %s\n' % str(e), file=sys.stderr)
      return 1
    except _ProcessError as e:
      print('Weston fail: %s\n' % str(e), file=sys.stderr)
      return 1
    finally:
      kill(weston_proc, 'weston')

      if os.path.exists(_weston_notify_socket_address()):
        os.remove(_weston_notify_socket_address())

      if os.path.exists(_weston_config_file_path()):
        os.remove(_weston_config_file_path())


def _weston_notify_socket_address():
  return os.path.join(tempfile.gettempdir(), '.xvfb.py-weston-notify.sock')


def _weston_config_file_path():
  return os.path.join(tempfile.gettempdir(), '.xvfb.py-weston.ini')


def _run_with_mutter(cmd, env, stdoutfile, cwd, mutter_display):
  with dbus_session(env):
    mutter_proc = None

    try:
      mutter_executable = './mutter'
      compositor_found, cmd = _run_with_wayland_common(mutter_executable, cmd,
                                                       env)
      if not compositor_found:
        # Ensure mutter is checked out if the compositor is not found.
        if not os.path.isdir(
            os.path.join(os.path.dirname(__file__), '..', 'third_party',
                         'mutter', 'src')):
          print(
              'In order to run tests using mutter, its sources need to be '
              'checked outexplicitly and built.\n'
              'Add \'"checkout_mutter": True\' in the "custom_vars" section '
              'of your .gclient file, and run gclient sync.\n'
              'Then build the test executable or mutter and run this script '
              'again.',
              file=sys.stderr)
          return 1
        return test_env.run_executable(cmd, env, stdoutfile, cwd)

      # Use headless wayland backend with a virtual monitor of appropriate size.
      mutter_cmd = [
          mutter_executable, '--headless',
          f'--virtual-monitor={mutter_display}', '--'
      ]
      cmd = mutter_cmd + cmd

      if '--mutter-debug-logging' in cmd:
        cmd.remove('--mutter-debug-logging')
        env = copy.deepcopy(env)
        env['G_MESSAGES_DEBUG'] = 'libmutter'
        env['MUTTER_DEBUG'] = 'input'

      return test_env.run_executable(cmd, env, stdoutfile, cwd)
    except _ProcessError as e:
      print('mutter fail: %s\n' % str(e), file=sys.stderr)
      return 1
    finally:
      kill(mutter_proc, 'mutter')


def _get_display_from_weston(weston_proc_pid):
  """Retrieves $WAYLAND_DISPLAY set by Weston.

  Returns the $WAYLAND_DISPLAY variable from one of weston's subprocesses.

  Weston updates this variable early in its startup in the main process, but we
  can only read the environment variables as they were when the process was
  created. Therefore we must use one of weston's subprocesses, which are all
  spawned with the new value for $WAYLAND_DISPLAY. Any of them will do, as they
  all have the same value set.

  Args:
    weston_proc_pid: The process of id of the main Weston process.

  Returns:
    the display set by Wayland, which clients can use to connect to.
  """

  # Take the parent process.
  parent = psutil.Process(weston_proc_pid)
  if parent is None:
    return None  # The process is not found. Give up.

  # Traverse through all the children processes and find one that has
  # $WAYLAND_DISPLAY set.
  children = parent.children(recursive=True)
  for process in children:
    weston_proc_display = process.environ().get('WAYLAND_DISPLAY')
    # If display is set, Weston could start successfully and we can use
    # that display for Wayland connection in Chromium.
    if weston_proc_display is not None:
      return weston_proc_display
  return None


class MutableBoolean(object):
  """Simple mutable boolean class. Used to be mutated inside an handler."""

  def __init__(self):
    self._val = False

  def setvalue(self, val):
    assert isinstance(val, bool)
    self._val = val

  def getvalue(self):
    return self._val


def raise_process_terminated(*_):
  raise _ProcessError('Terminated')


def find_display():
  """Iterates through X-lock files to find an available display number.

  The lower bound follows xvfb-run standard at 99, and the upper bound
  is set to 119.

  Returns:
    A string of a random available display number for Xvfb ':{99-119}'.

  Raises:
    _ProcessError: Raised when displays 99 through 119 are unavailable.
  """

  available_displays = [
      d for d in range(99, 120)
      if not os.path.isfile('/tmp/.X{}-lock'.format(d))
  ]
  if available_displays:
    return ':{}'.format(random.choice(available_displays))
  raise _ProcessError('Failed to find display number')


def _set_xdg_runtime_dir(env):
  """Sets the $XDG_RUNTIME_DIR variable if it hasn't been set before."""
  runtime_dir = env.get('XDG_RUNTIME_DIR')
  if not runtime_dir:
    runtime_dir = '/tmp/xdg-tmp-dir/'
    if not os.path.exists(runtime_dir):
      os.makedirs(runtime_dir, 0o700)
    env['XDG_RUNTIME_DIR'] = runtime_dir


def main():
  usage = ('[command [--no-xvfb or --use-xvfb or --use-weston] args...]\n'
           '\t --no-xvfb\t\tTurns off all X11 backings (Xvfb and Xorg).\n'
           '\t --use-xvfb\t\tForces legacy Xvfb backing instead of Xorg.\n'
           '\t --use-weston\t\tEnable Weston Wayland server.\n'
           '\t --use-mutter\t\tEnable Mutter Wayland server.\n'
           '\t --mutter-display\tSpecify Mutter Display Resolution as WxH.')
  # TODO(crbug.com/326283384): Argparse-ify this.
  if len(sys.argv) < 2:
    print(usage + '\n', file=sys.stderr)
    return 2

  # If the user still thinks the first argument is the execution directory then
  # print a friendly error message and quit.
  if os.path.isdir(sys.argv[1]):
    print('Invalid command: \"%s\" is a directory\n' % sys.argv[1],
          file=sys.stderr)
    print(usage + '\n', file=sys.stderr)
    return 3

  return run_executable(sys.argv[1:], os.environ.copy())


if __name__ == '__main__':
  sys.exit(main())
