blob: fb07842e5341c6ba129d884467ec96d48d27a467 [file] [log] [blame]
#!/usr/bin/env vpython
# Copyright 2014 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.
# [VPYTHON:BEGIN]
# python_version: "2.7"
# [VPYTHON:END]
"""Convenience script for expect_tests"""
from __future__ import absolute_import
from __future__ import print_function
assert __name__ == '__main__'
import os
import subprocess
import sys
INFRA_ROOT = os.path.dirname(os.path.abspath(__file__))
# Allowlist of packages to test on Windows.
WIN_ENABLED_PACKAGES = [
'infra/libs/decorators',
'infra/libs/gitiles',
'infra/libs/process_invocation',
'infra/libs/service_utils',
'infra/libs/state_machine',
'infra/tools/dockerbuild', # for wheel smoke tests
'infra/services/service_manager',
'packages/infra_libs/infra_libs/infra_types',
'packages/infra_libs/infra_libs/logs',
'packages/infra_libs/infra_libs/time_functions',
'packages/infra_libs/infra_libs/ts_mon',
]
def usage():
print("""\nUsage: %s <action> [<test names>] [<expect_tests options>]
where <action> is one of: list, test, train, debug.
Examples:
Run all tests:
./test.py test
Run all tests in the given package:
./test.py test infra
./test.py test appengine/cr-buildbucket
Run all tests and generate an HTML report:
./test.py test infra --html-report /path/to/report/folder
Run one given test in the infra package:
./test.py test infra/libs/git2/test:*testCommitBogus
See expect_tests documentation for more details
""" % sys.argv[0])
def get_modules_with_coveragerc(root_module):
"""Returns submodules that have .coveragerc file present."""
root_dir = os.path.join(INFRA_ROOT, root_module.replace('/', os.sep))
if not os.path.isdir(root_dir):
return []
return [
'%s/%s' % (root_module, d)
for d in os.listdir(root_dir)
if os.path.isfile(os.path.join(root_dir, d, '.coveragerc'))
]
# Parse command-line arguments
if len(sys.argv) == 1:
usage()
sys.exit(1)
else:
if not sys.argv[1] in ('list', 'train', 'test', 'debug'):
usage()
sys.exit(1)
if sys.platform == 'win32':
python_bin = os.path.join('ENV', 'Scripts', 'python')
expect_tests_path = os.path.join('ENV', 'Scripts', 'expect_tests')
else:
python_bin = os.path.join('ENV', 'bin', 'python')
expect_tests_path = os.path.join('ENV', 'bin', 'expect_tests')
command = sys.argv[1]
args = sys.argv[2:]
modules = []
flags = []
# BUG: this will append everything after the first flag to `flags`. Thus,
# it fails to catch when (a) someone doesn't pass a directory after
# "--html-report", nor (b) if they pass multiple directories after that
# flag.
for arg in args:
if arg.startswith('-'):
flags.append(arg)
continue
if flags:
flags.append(arg)
else:
modules.append(arg)
# Set up default list of packages/directories if none have been provided.
if not modules:
# On Windows, test only allowlisted subset of 'infra' and 'packages' modules.
if sys.platform == 'win32':
modules.extend([
p for p in WIN_ENABLED_PACKAGES
if os.path.isdir(os.path.join(INFRA_ROOT, p))
])
else:
modules.extend(['infra'])
modules.extend(get_modules_with_coveragerc('packages'))
# Test shared GAE code and individual GAE apps only on 64-bit Posix. This
# matches GAE environment. Skip this if running tests when testing
# infra_python CIPD package integrity: the package doesn't have appengine
# code in it.
if os.path.isdir(os.path.join(INFRA_ROOT, 'appengine')):
test_gae = sys.platform != 'win32' and sys.maxsize == (2 ** 63) - 1
if test_gae:
modules.append('appengine_module')
modules.extend(get_modules_with_coveragerc('appengine'))
os.environ['PYTHONPATH'] = ''
os.chdir(INFRA_ROOT)
if '--help' not in flags and '-h' not in flags:
subprocess.check_call(
[python_bin, os.path.join('bootstrap', 'remove_orphaned_pycs.py')])
else:
usage()
sys.exit(subprocess.call([python_bin, expect_tests_path, command, '--help']))
if sys.platform == 'win32' and '--force-coverage' not in flags:
flags.append('--no-coverage')
exit_code = 0
failed_modules = []
for module in modules:
print('Running %s...' % module)
module_flags = flags[:]
# Remove any test glob, which comes after semicolon (:) and convert to a path.
module_path = module.split(':')[0].replace('/', os.sep)
if not any(flag.startswith('--coveragerc') for flag in module_flags):
module_coveragerc = os.path.join(INFRA_ROOT, module_path, '.coveragerc')
module_flags.append('--coveragerc=%s' % module_coveragerc)
if not any(flag.startswith('--html-report-subdir') for flag in module_flags):
module_flags.append('--html-report-subdir=%s' % module_path)
cmd = [python_bin, expect_tests_path, command, module] + module_flags
module_exit_code = subprocess.call(cmd)
exit_code = module_exit_code or exit_code
if module_exit_code:
failed_modules.append(module)
if exit_code:
print()
print('Tests failed in modules:\n %s' % '\n '.join(failed_modules))
if '--html-report' not in flags:
print('\nFor detailed coverage report and per-line branch coverage,')
print('rerun with --html-report <dir>')
else:
print('All tests passed.')
sys.exit(exit_code)