blob: a081817f62703d747508b521a146f8c1000ebfb0 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Wrapper script for running XR browser tests properly.
The XR browser tests require some additional setup to run properly, for example
setting ACLs on Windows in order to allow the sandboxed process to work
properly. This setup can technically be done in the test itself, but can take
a significant amount of time, causing tests to time out.
This could be worked around by changing the test runner being used from
//chrome/test/base/browser_tests_runner.cc to a custom one that performs the
setup outside of any tests, but that duplicates code and could potentially make
the XR tests miss any changes made to the base file.
"""
import argparse
import json
import logging
import os
import subprocess
import sys
# These ACLs allow the app container users (the really long numerical strings)
# to read and execute files in whatever directory they're applied to (in this
# case, the output directory). This is required in order for the isolated XR
# device service to work in a sandboxed process. These would normally be set
# during installation, but have to be manually set for tests since the installer
# isn't used.
ACL_STRINGS = [
'S-1-15-3-1024-2302894289-466761758-1166120688-1039016420-2430351297-4240214049-4028510897-3317428798:(OI)(CI)(RX)',
'S-1-15-3-1024-3424233489-972189580-2057154623-747635277-1604371224-316187997-3786583170-1043257646:(OI)(CI)(RX)',
]
DEFAULT_TRACING_CATEGORIES = [
'blink',
'cc',
'cpu_profiler',
'gpu',
'xr',
]
def GetTestExecutable():
test_executable = 'xr_browser_tests_binary'
if sys.platform == 'win32':
test_executable += '.exe'
return test_executable
def ResetACLs(path):
logging.warning(
'Setting ACLs on %s to default. This might take a while.', path)
try:
# It's normally fine to inherit the ACLs from parents, but in this case,
# we need to explicitly reset every file via /t.
_ = subprocess.check_output(
['icacls', path, '/reset', '/t'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
logging.error('Failed to reset ACLs on path %s', path)
logging.error('Command output: %s', e.output)
sys.exit(e.returncode)
def SetupWindowsACLs(acl_dir):
try:
existing_acls = subprocess.check_output(
['icacls', acl_dir], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
logging.error('Failed to retrieve existing ACLs for directory %s', acl_dir)
logging.error('Command output: %s', e.output)
sys.exit(e.returncode)
have_reset = False
for acl in ACL_STRINGS:
if acl not in existing_acls:
if not have_reset:
# Some bots seem to have explicit ACLs set on the isolated input
# directory. Most still have the default, so it appears to be leftover
# from some previous thing and no longer actively used. So, if we
# haven't set our ACLs before on this directory, reset them to default
# first since the explicit ones can cause issues with ours not being
# inherited.
have_reset = True
ResetACLs(acl_dir)
try:
logging.warning(
'ACL %s not set on output directory. Attempting to set.', acl)
_ = subprocess.check_output(['icacls', acl_dir, '/grant', '*%s' % acl],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
logging.error('Failed to apply ACL %s to directory %s', acl, acl_dir)
logging.error('Command output: %s', e.output)
sys.exit(e.returncode)
def SetupTracingIfNecessary(args):
if not args.tracing_output_directory:
return []
tracing_categories = args.tracing_categories or DEFAULT_TRACING_CATEGORIES
with open(os.path.join(args.tracing_output_directory, 'traceconfig.json'),
'w') as trace_config:
json.dump({
'trace_config': {
'record_mode': 'record-until-full',
'included_categories': tracing_categories,
},
'startup_duraton': 0,
'result_directory': args.tracing_output_directory,
}, trace_config)
return ['--trace-config-file=%s' % trace_config.name]
def CreateArgumentParser():
parser = argparse.ArgumentParser(
description='This is a wrapper script around %s. To view help for that, '
'run `%s --help`.' % (
GetTestExecutable(), GetTestExecutable()))
group = parser.add_argument_group(
title='Tracing',
description='Arguments related to running the tests with tracing enabled')
group.add_argument('--tracing-output-directory', type=os.path.abspath,
help='The directory to store trace logs in. Setting this '
'enables tracing in the test.')
group.add_argument('--tracing-category', action='append', default=[],
dest='tracing_categories',
help='Add a tracing category to capture. Can be passed '
'multiple times, once for each category. If '
'unspecified, defaults to %s'
% DEFAULT_TRACING_CATEGORIES)
return parser
def main():
parser = CreateArgumentParser()
args, rest_args = parser.parse_known_args()
if sys.platform == 'win32':
# This should be copied into the root of the output directory, so the
# directory this file is in should be the directory we want to change the
# ACLs of.
SetupWindowsACLs(os.path.abspath(os.path.dirname(__file__)))
tracing_args = SetupTracingIfNecessary(args)
test_executable = os.path.abspath(
os.path.join(os.path.dirname(__file__), GetTestExecutable()))
sys.exit(subprocess.call(
[test_executable, '--run-through-xr-wrapper-script'] +
tracing_args + rest_args))
if __name__ == '__main__':
main()