mopar是什么牌子| 莱赛尔是什么面料| 什么是精神出轨| 丢包率是什么意思| 什么药治尿酸高最有效| 浮木是什么意思| tf口红属于什么档次| 什么饮料能解酒| 特警属于什么编制| 水字五行属什么| 肉松可以做什么美食| 狗为什么会吐| 孔子是什么时期的人| 下面干涩是什么原因导致的| 脑供血不足吃什么中药| 骨密度检查是查什么| 两个gg是什么牌子的包包| 血管是什么颜色的| 暇步士是什么档次品牌| 在家无聊可以做什么| 腰椎退行性改变什么意思| 脾胃湿热吃什么中成药| 为什么会有同性恋| 名节是什么意思| 雪花飘飘北风萧萧是什么歌| 媳妇是什么意思| 话梅泡水喝有什么好处和坏处| 眼屎多什么原因| 咽炎咳嗽吃什么| 什么水果不含糖| 什么样的女人不能娶| 眼睛经常充血是什么原因引起的| 电视黑屏是什么原因| 小儿割包皮挂什么科| 蓝加黄是什么颜色| 前胸后背疼挂什么科| 老犯困是什么原因| 糖类抗原是什么意思| 置换补贴什么意思| 手抖吃什么药| 什么药治便秘效果最好最快| 喜欢紫色的女人是什么性格| 穗是什么意思| 低热是什么症状| 1944年属什么生肖| 血压偏低吃什么| 甲状旁腺分泌什么激素| 血管没有弹性是什么原因| 3月15号是什么星座| 嘴角上扬是什么意思| 月子餐吃什么| sp是什么| 什么是业力| 王字旁行念什么| 即兴表演是什么意思| 扁桃体炎吃什么药最好效果好| 我国四大发明是什么| 硒片什么牌子好| 阳字属于五行属什么| 头部出汗多是什么原因| 麻是什么植物| 喝什么对嗓子好| 吃什么容易长胖| 小孩口腔溃疡是什么原因引起的| 悉心栽培什么意思| gl小说是什么意思| 阴道口瘙痒是什么原因| 空腹洗澡有什么危害| 胰腺在人体起什么作用| 什么是树洞| 梦见黄瓜是什么意思| 手指头发麻是什么原因| mt是什么缩写| 7月8号是什么星座| 吊龙是什么| 女人白带多什么原因| 伤情鉴定需要什么材料| edifier是什么牌子| 绞丝旁一个奇念什么| 十月初三是什么星座| 海胆是什么| 经期头疼是什么原因怎么办| 为什么吐后反而舒服了| 生长激素是什么| 人为什么会死| 5.16号是什么星座| 什么叫游走性关节疼痛| 3月27是什么星座| 爻是什么意思| 体脂率是什么| lu是什么单位| 红薯什么时候掐尖| 永垂不朽是什么意思| 男人趴着睡觉说明什么| 什么颜色属火| 对蚊子过敏是什么症状| 尿潜血1十是什么原因| 倒刺是什么原因引起的| 马非读什么| 舌头火辣辣的是什么病| 人造革是什么材质| 医院手环颜色代表什么| other是什么品牌| 嘴唇干裂脱皮是什么原因| 越南古代叫什么| 驻马店有什么大学| 吴用属什么生肖| 天葬是什么| 大千世界什么意思| 为什么拔罐肩膀最黑| 水当当是什么意思| longines是什么牌子| 睡觉流口水吃什么药| 手机账号是什么| 梅兰竹菊代表什么生肖| 青光眼是什么原因引起的| 什么是根号| 吃什么东西可以长高| 变异性哮喘什么症状| 梦见抓了好多鱼是什么意思| 东厂是什么意思| 失眠吃什么食物效果最好| 严重失眠吃什么药| 五年生存率是什么意思| ep什么意思| 嘴唇干裂是什么原因引起的| 黔驴技穷是什么意思| 青瓜是什么瓜| 低血压要注意些什么| 拉分是什么意思| 种生基是什么意思| 倾向是什么意思| napoleon是什么酒| 尿常规能查出什么| o型血和ab型血生的孩子是什么血型| 花骨朵是什么意思| 梦见梅花鹿是什么预兆| 色氨酸是什么| 什么锅好| 食神生财是什么意思| 子宫增厚是什么原因| 五行缺土戴什么| sv是什么意思| 颠是什么意思| 晚上口苦是什么原因引起的| 耐药性什么意思| 1980年属什么| 好饭不怕晚什么意思| 黄瓜炒什么菜好吃| 沙拉是什么| 沉积是什么意思| 鸡心为什么不建议吃| 夺嫡是什么意思| 11月20号什么星座| 血糖高可以喝什么粥| 感冒喉咙痛吃什么药好| 阴道炎吃什么消炎药| 康普茶是什么| 脚踩按摩垫有什么好处| 巨婴是什么意思| 为什么男的叫鸭子| 桃子不能和什么水果一起吃| 坐车头疼是什么原因| 什么光会给人带来痛苦| 生理期提前是什么原因| 耳鸣吃什么药最有效| 尿不尽是什么症状| 什么是性早熟| 新五行属什么| 哈密瓜为什么叫哈密瓜| 2014年什么年| 实体店是什么意思| 小三阳和大三阳有什么区别| 肿瘤标志物是什么| 胰腺在什么位置图片| 95年属什么生肖婚配表| 什么体质不易怀孕| 腱鞘炎什么症状| sayno是什么意思| 牛肉和什么包饺子好吃| 麦芽糊精是什么东西| 下巴有痣代表什么| 手指关节肿大是什么原因| 决明子有什么作用| 心悸是什么意思| 南瓜和什么不能一起吃| 炖羊骨头放什么调料| 属鼠的贵人是什么属相| 太阳筋疼是什么原因| 3月12日什么星座| 怕热出汗多是什么原因| 一什么宝石| 浅笑嫣然是什么意思| 尿常规白细胞高是什么原因| 怀孕感冒可以吃什么药| 烟雾病是什么原因引起的| 转述句什么意思| 四级警长是什么级别| 强直性脊柱炎挂什么科| 平动是什么意思| 男生为什么会勃起| 无痛人流和普通人流有什么区别| 胃寒吃什么药最有效| 不以规矩下一句是什么| 尿道下裂是什么意思| 主心骨是什么意思| 自然人是什么意思| 灵芝孢子粉治什么病| 什么时候喝咖啡能减肥| 吃什么能排毒体内毒素| 颈椎痛吃什么药最好| wm是什么牌子| 后脑勺发麻是什么原因| 木樨是什么意思| 病毒感染咳嗽吃什么药| 朱迅是什么民族| 反目成仇是什么意思| 爱吃甜食是什么原因| 梦见表姐是什么意思| 什么芦荟可以直接擦脸| 2017什么年| 鸡枞菌生长在什么地方| 拉大便肛门口疼痛什么原因| 缪读什么| 栀子有什么功效| 78年属马的是什么命| 马失前蹄下一句是什么| 儿童个子矮小看什么科| 真金白银是什么意思| 犹豫的反义词是什么| 在水一方是什么意思| 什么星星| 睡觉磨牙是什么原因引起的| 猫咪吐黄水有泡沫没有精神吃什么药| 兵部尚书相当于现在的什么官| 九一八事变是什么意思| 11月7日什么星座| 单核细胞是什么意思| 脉压差大是什么原因| 隐血阳性什么意思| 胃不舒服想吐是什么原因| 肾阳虚吃什么药好| 胰腺炎恢复期吃什么好| 什么是脱脂牛奶| 月字旁与什么有关| 是非是什么意思| gravy是什么意思| 重度肠上皮化生是什么意思| 什么东西能戒酒| 附骨疽是什么病| 小孩肚脐周围疼是什么原因| 馒头是什么做的| 蜘蛛侠叫什么| 讽刺是什么意思| a型血和ab型血生的孩子是什么血型| 脊椎炎有什么症状| 第二性征是什么| fps是什么意思| 反流性咽喉炎吃什么药| 蛋白质偏高是什么原因| 吃了避孕药有什么反应| 澳大利亚有什么动物| 戒断反应是什么| 黑色素缺失吃什么补充最快| 百度
blob: 056fa7e1cd052ae8aa174ed5514ed75decb496b3 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Builds and runs a test by filename.
This script finds the appropriate test suites for the specified test files or
directories, builds it, then runs it with the (optionally) specified filter,
passing any extra args on to the test runner.
Examples:
# Run the test target for bit_cast_unittest.cc. Use a custom test filter instead
# of the automatically generated one.
autotest.py -C out/Desktop bit_cast_unittest.cc --gtest_filter=BitCastTest*
# Find and run UrlUtilitiesUnitTest.java's tests, pass remaining parameters to
# the test binary.
autotest.py -C out/Android UrlUtilitiesUnitTest --fast-local-dev -v
# Run all tests under base/strings.
autotest.py -C out/foo --run-all base/strings
# Run tests in multiple files or directories.
autotest.py -C out/foo base/strings base/pickle_unittest.cc
# Run only the test on line 11. Useful when running autotest.py from your text
# editor.
autotest.py -C out/foo --line 11 base/strings/strcat_unittest.cc
"""
import argparse
import json
import locale
import os
import re
import shlex
import subprocess
import sys
import shutil
from enum import Enum
from pathlib import Path
# Don't write pyc files to the src tree, which show up in version control
# in some environments.
sys.dont_write_bytecode = True
USE_PYTHON_3 = f'This script will only run under python3.'
SRC_DIR = Path(__file__).parent.parent.resolve()
sys.path.append(str(SRC_DIR / 'build'))
import gn_helpers
sys.path.append(str(SRC_DIR / 'build' / 'android'))
from pylib import constants
DEPOT_TOOLS_DIR = SRC_DIR / 'third_party' / 'depot_tools'
DEBUG = False
# Some test suites use suffixes that would also match non-test-suite targets.
# Those test suites should be manually added here.
_TEST_TARGET_ALLOWLIST = [
# The tests below this line were output from the ripgrep command just below:
'//ash:ash_pixeltests',
'//build/rust/tests/test_serde_json_lenient:test_serde_json_lenient',
'//chrome/browser/apps/app_service/app_install:app_install_fuzztests',
'//chrome/browser/glic/e2e_test:glic_internal_e2e_interactive_ui_tests',
'//chrome/browser/mac:install_sh_test',
'//chrome/browser/metrics/perf:profile_provider_unittest',
'//chrome/browser/privacy_sandbox/notice:fuzz_tests',
'//chrome/browser/web_applications:web_application_fuzztests',
'//chromecast/media/base:video_plane_controller_test',
'//chromecast/metrics:cast_metrics_unittest',
'//chrome/enterprise_companion:enterprise_companion_integration_tests',
'//chrome/enterprise_companion:enterprise_companion_tests',
'//chrome/installer/gcapi:gcapi_test',
'//chrome/installer/test:upgrade_test',
'//chromeos/ash/components/kiosk/vision:kiosk_vision_unit_tests',
'//chrome/test/android:chrome_public_apk_baseline_profile_generator',
'//chrome/test:unit_tests',
'//clank/javatests:chrome_apk_baseline_profile_generator',
'//clank/javatests:chrome_smoke_test',
'//clank/javatests:monochrome_bundle_smoke_test',
'//clank/javatests:trichrome_chrome_google_bundle_smoke_test',
'//components/chromeos_camera:jpeg_decode_accelerator_unittest',
'//components/exo/wayland:wayland_client_compatibility_tests',
'//components/exo/wayland:wayland_client_tests',
'//components/facilitated_payments/core/validation:pix_code_validator_fuzzer',
'//components/ip_protection:components_ip_protection_fuzztests',
'//components/minidump_uploader:minidump_uploader_test',
'//components/paint_preview/browser:paint_preview_browser_unit_tests',
'//components/paint_preview/common:paint_preview_common_unit_tests',
'//components/paint_preview/renderer:paint_preview_renderer_unit_tests',
'//components/services/paint_preview_compositor:paint_preview_compositor_unit_tests',
'//components/translate/core/language_detection:language_detection_util_fuzztest',
'//components/webcrypto:webcrypto_testing_fuzzer',
'//components/zucchini:zucchini_integration_test',
'//content/test/fuzzer:devtools_protocol_encoding_json_fuzzer',
'//fuchsia_web/runners:cast_runner_integration_tests',
'//fuchsia_web/webengine:web_engine_integration_tests',
'//google_apis/gcm:gcm_unit_tests',
'//gpu:gl_tests',
'//gpu:gpu_benchmark',
'//gpu/vulkan/android:vk_tests',
'//ios/web:ios_web_inttests',
'//ios/web_view:ios_web_view_inttests',
'//media/cdm:aes_decryptor_fuzztests',
'//media/formats:ac3_util_fuzzer',
'//media/gpu/chromeos:image_processor_test',
'//media/gpu/v4l2:v4l2_unittest',
'//media/gpu/vaapi/test/fake_libva_driver:fake_libva_driver_unittest',
'//media/gpu/vaapi:vaapi_unittest',
'//native_client/tests:large_tests',
'//native_client/tests:medium_tests',
'//native_client/tests:small_tests',
'//sandbox/mac:sandbox_mac_fuzztests',
'//sandbox/win:sbox_integration_tests',
'//sandbox/win:sbox_validation_tests',
'//testing/libfuzzer/fuzzers:libyuv_scale_fuzztest',
'//testing/libfuzzer/fuzzers:paint_vector_icon_fuzztest',
'//third_party/blink/renderer/controller:blink_perf_tests',
'//third_party/blink/renderer/core:css_parser_fuzzer',
'//third_party/blink/renderer/core:inspector_ghost_rules_fuzzer',
'//third_party/blink/renderer/platform/loader:unencoded_digest_fuzzer',
'//third_party/crc32c:crc32c_benchmark',
'//third_party/crc32c:crc32c_tests',
'//third_party/dawn/src/dawn/tests/benchmarks:dawn_benchmarks',
'//third_party/highway:highway_tests',
'//third_party/ipcz/src:ipcz_tests',
'//third_party/libaom:av1_encoder_fuzz_test',
'//third_party/libaom:test_libaom',
'//third_party/libvpx:test_libvpx',
'//third_party/libvpx:vp8_encoder_fuzz_test',
'//third_party/libvpx:vp9_encoder_fuzz_test',
'//third_party/libwebp:libwebp_advanced_api_fuzzer',
'//third_party/libwebp:libwebp_animation_api_fuzzer',
'//third_party/libwebp:libwebp_animencoder_fuzzer',
'//third_party/libwebp:libwebp_enc_dec_api_fuzzer',
'//third_party/libwebp:libwebp_huffman_fuzzer',
'//third_party/libwebp:libwebp_mux_demux_api_fuzzer',
'//third_party/libwebp:libwebp_simple_api_fuzzer',
'//third_party/opus:test_opus_api',
'//third_party/opus:test_opus_decode',
'//third_party/opus:test_opus_encode',
'//third_party/opus:test_opus_padding',
'//third_party/pdfium:pdfium_embeddertests',
'//third_party/pffft:pffft_unittest',
'//third_party/rapidhash:rapidhash_fuzztests',
'//ui/ozone:ozone_integration_tests',
]
r"""
You can run this command to find test targets that do not match these regexes,
and use it to update _TEST_TARGET_ALLOWLIST.
rg '^(instrumentation_test_runner|test)\("([^"]*)' -o -g'BUILD.gn' -r'$2' -N \
| rg -v '(_browsertests|_perftests|_wpr_tests|_unittests)$' \
| rg '^(.*)/BUILD.gn(.*)$' -r'\'//$1$2\',' \
| sort
And you can use a command like this to find source_set targets that do match
the test target regex (ideally this is minimal).
rg '^source_set\("([^"]*)' -o -g'BUILD.gn' -r'$1' -N | \
rg '(_browsertests|_perftests|_wpr_tests|_unittests)$'
"""
_TEST_TARGET_REGEX = re.compile(
r'(_browsertests|_perftests|_wpr_tests|_unittests)$')
_PREF_MAPPING_FILE_PATTERN = re.escape(
str(Path('components') / 'policy' / 'test' / 'data' / 'pref_mapping') +
r'/') + r'.*\.json'
TEST_FILE_NAME_REGEX = re.compile(
r'(.*Test\.java)' +
r'|(.*_[a-z]*test(?:_win|_mac|_linux|_chromeos|_android)?\.(cc|mm))' +
r'|(' + _PREF_MAPPING_FILE_PATTERN + r')')
# Some tests don't directly include gtest.h and instead include it via gmock.h
# or a test_utils.h file, so make sure these cases are captured. Also include
# files that use <...> for #includes instead of quotes.
GTEST_INCLUDE_REGEX = re.compile(
r'#include.*(gtest|gmock|_test_utils|browser_test)\.h("|>)')
def ExitWithMessage(*args):
print(*args, file=sys.stderr)
sys.exit(1)
class TestValidity(Enum):
NOT_A_TEST = 0 # Does not match test file regex.
MAYBE_A_TEST = 1 # Matches test file regex, but doesn't include gtest files.
VALID_TEST = 2 # Matches test file regex and includes gtest files.
def FindRemoteCandidates(target):
"""Find files using a remote code search utility, if installed."""
if not shutil.which('cs'):
return []
results = RunCommand([
'cs', '-l',
# Give the local path to the file, if the file exists.
'--local',
f'file:{target}',
# Restrict our search to Chromium
'git:chrome-internal/codesearch/chrome/src@main']).splitlines()
exact = set()
close = set()
for filename in results:
file_validity = IsTestFile(filename)
if file_validity is TestValidity.VALID_TEST:
exact.add(filename)
elif file_validity is TestValidity.MAYBE_A_TEST:
close.add(filename)
return list(exact), list(close)
def IsTestFile(file_path):
if not TEST_FILE_NAME_REGEX.match(file_path):
return TestValidity.NOT_A_TEST
if file_path.endswith('.cc') or file_path.endswith('.mm'):
# Try a bit harder to remove non-test files for c++. Without this,
# 'autotest.py base/' finds non-test files.
try:
with open(file_path, 'r', encoding='utf-8') as f:
if GTEST_INCLUDE_REGEX.search(f.read()) is not None:
return TestValidity.VALID_TEST
except IOError:
pass
# It may still be a test file, even if it doesn't include a gtest file.
return TestValidity.MAYBE_A_TEST
return TestValidity.VALID_TEST
class CommandError(Exception):
"""Exception thrown when a subcommand fails."""
def __init__(self, command, return_code, output=None):
Exception.__init__(self)
self.command = command
self.return_code = return_code
self.output = output
def __str__(self):
message = (f'\n***\nERROR: Error while running command {self.command}'
f'.\nExit status: {self.return_code}\n')
if self.output:
message += f'Output:\n{self.output}\n'
message += '***'
return message
def StreamCommandOrExit(cmd, **kwargs):
try:
subprocess.check_call(cmd, **kwargs)
except subprocess.CalledProcessError as e:
sys.exit(1)
def RunCommand(cmd, **kwargs):
try:
# Set an encoding to convert the binary output to a string.
return subprocess.check_output(
cmd, **kwargs, encoding=locale.getpreferredencoding())
except subprocess.CalledProcessError as e:
raise CommandError(e.cmd, e.returncode, e.output) from None
def BuildTestTargets(out_dir, targets, dry_run, quiet):
"""Builds the specified targets with ninja"""
cmd = gn_helpers.CreateBuildCommand(out_dir) + targets
print('Building: ' + shlex.join(cmd))
if (dry_run):
return True
completed_process = subprocess.run(cmd,
capture_output=quiet,
encoding='utf-8')
if completed_process.returncode != 0:
if quiet:
before, _, after = completed_process.stdout.partition('stderr:')
if not after:
before, _, after = completed_process.stdout.partition('stdout:')
if after:
print(after)
else:
print(before)
return False
return True
def RecursiveMatchFilename(folder, filename):
current_dir = os.path.split(folder)[-1]
if current_dir.startswith('out') or current_dir.startswith('.'):
return [[], []]
exact = []
close = []
try:
with os.scandir(folder) as it:
for entry in it:
if (entry.is_symlink()):
continue
if (entry.is_file() and filename in entry.path and
not os.path.basename(entry.path).startswith('.')):
file_validity = IsTestFile(entry.path)
if file_validity is TestValidity.VALID_TEST:
exact.append(entry.path)
elif file_validity is TestValidity.MAYBE_A_TEST:
close.append(entry.path)
if entry.is_dir():
# On Windows, junctions are like a symlink that python interprets as a
# directory, leading to exceptions being thrown. We can just catch and
# ignore these exceptions like we would ignore symlinks.
try:
matches = RecursiveMatchFilename(entry.path, filename)
exact += matches[0]
close += matches[1]
except FileNotFoundError as e:
if DEBUG:
print(f'Failed to scan directory "{entry}" - junction?')
pass
except PermissionError:
print(f'Permission error while scanning {folder}')
return [exact, close]
def FindTestFilesInDirectory(directory):
test_files = []
if DEBUG:
print('Test files:')
for root, _, files in os.walk(directory):
for f in files:
path = os.path.join(root, f)
file_validity = IsTestFile(path)
if file_validity is TestValidity.VALID_TEST:
if DEBUG:
print(path)
test_files.append(path)
elif DEBUG and file_validity is TestValidity.MAYBE_A_TEST:
print(path + ' matched but doesn\'t include gtest files, skipping.')
return test_files
def FindMatchingTestFiles(target, remote_search=False):
# Return early if there's an exact file match.
if os.path.isfile(target):
if test_file := _FindTestForFile(target):
return [test_file]
ExitWithMessage(f"{target} doesn't look like a test file")
# If this is a directory, return all the test files it contains.
if os.path.isdir(target):
files = FindTestFilesInDirectory(target)
if not files:
ExitWithMessage('No tests found in directory')
return files
if sys.platform.startswith('win32') and os.path.altsep in target:
# Use backslash as the path separator on Windows to match os.scandir().
if DEBUG:
print('Replacing ' + os.path.altsep + ' with ' + os.path.sep + ' in: '
+ target)
target = target.replace(os.path.altsep, os.path.sep)
if DEBUG:
print('Finding files with full path containing: ' + target)
if remote_search:
exact, close = FindRemoteCandidates(target)
if not exact and not close:
print('Failed to find remote candidates; searching recursively')
exact, close = RecursiveMatchFilename(SRC_DIR, target)
else:
exact, close = RecursiveMatchFilename(SRC_DIR, target)
if DEBUG:
if exact:
print('Found exact matching file(s):')
print('\n'.join(exact))
if close:
print('Found possible matching file(s):')
print('\n'.join(close))
if len(exact) >= 1:
# Given "Foo", don't ask to disambiguate ModFoo.java vs Foo.java.
more_exact = [
p for p in exact if os.path.basename(p) in (target, f'{target}.java')
]
if len(more_exact) == 1:
test_files = more_exact
else:
test_files = exact
else:
test_files = close
if len(test_files) > 1:
if len(test_files) < 10:
test_files = [HaveUserPickFile(test_files)]
else:
# Arbitrarily capping at 10 results so we don't print the name of every
# file in the repo if the target is poorly specified.
test_files = test_files[:10]
ExitWithMessage(f'Target "{target}" is ambiguous. Matching files: '
f'{test_files}')
if not test_files:
ExitWithMessage(f'Target "{target}" did not match any files.')
return test_files
def _FindTestForFile(target: os.PathLike) -> str | None:
root, ext = os.path.splitext(target)
# If the target is a C++ implementation file, try to guess the test file.
# Candidates should be ordered most to least promising.
test_candidates = [target]
if ext == '.h':
# `*_unittest.{cc,mm}` are both possible.
test_candidates.append(f'{root}_unittest.cc')
test_candidates.append(f'{root}_unittest.mm')
elif ext == '.cc' or ext == '.mm':
test_candidates.append(f'{root}_unittest{ext}')
else:
return target
maybe_valid = []
for candidate in test_candidates:
if not os.path.isfile(candidate):
continue
validity = IsTestFile(candidate)
if validity is TestValidity.VALID_TEST:
return candidate
elif validity is TestValidity.MAYBE_A_TEST:
maybe_valid.append(candidate)
return maybe_valid[0] if maybe_valid else None
def HaveUserPickFile(paths):
paths = sorted(paths, key=lambda p: (len(p), p))
path_list = '\n'.join(f'{i}. {t}' for i, t in enumerate(paths))
while True:
user_input = input(f'Please choose the path you mean.\n{path_list}\n')
try:
value = int(user_input)
return paths[value]
except (ValueError, IndexError):
print('Try again')
def HaveUserPickTarget(paths, targets):
# Cap to 10 targets for convenience [0-9].
targets = targets[:10]
target_list = '\n'.join(f'{i}. {t}' for i, t in enumerate(targets))
user_input = input(f'Target "{paths}" is used by multiple test targets.\n' +
target_list + '\nPlease pick a target by its numeric index'
'listed below: ')
try:
value = int(user_input)
return targets[value]
except (ValueError, IndexError):
print('Value entered was not a numeric index listed above. Trying again.')
return HaveUserPickTarget(paths, targets)
# A persistent cache to avoid running gn on repeated runs of autotest.
class TargetCache:
def __init__(self, out_dir):
self.out_dir = out_dir
self.path = os.path.join(out_dir, 'autotest_cache')
self.gold_mtime = self.GetBuildNinjaMtime()
self.cache = {}
try:
mtime, cache = json.load(open(self.path, 'r'))
if mtime == self.gold_mtime:
self.cache = cache
except Exception:
pass
def Save(self):
with open(self.path, 'w') as f:
json.dump([self.gold_mtime, self.cache], f)
def Find(self, test_paths):
key = ' '.join(test_paths)
return self.cache.get(key, None)
def Store(self, test_paths, test_targets):
key = ' '.join(test_paths)
self.cache[key] = test_targets
def GetBuildNinjaMtime(self):
return os.path.getmtime(os.path.join(self.out_dir, 'build.ninja'))
def IsStillValid(self):
return self.GetBuildNinjaMtime() == self.gold_mtime
def _TestTargetsFromGnRefs(targets):
# First apply allowlists:
ret = [t for t in targets if '__' not in t]
ret = [
t for t in ret
if _TEST_TARGET_REGEX.search(t) or t in _TEST_TARGET_ALLOWLIST
]
if ret:
return ret
_SUBTARGET_SUFFIXES = (
'__java_binary', # robolectric_binary()
'__test_runner_script', # test() targets
'__test_apk', # instrumentation_test_apk() targets
)
ret = []
for suffix in _SUBTARGET_SUFFIXES:
ret.extend(t[:-len(suffix)] for t in targets if t.endswith(suffix))
return ret
def FindTestTargets(target_cache, out_dir, paths, run_all):
# Normalize paths, so they can be cached.
paths = [os.path.realpath(p) for p in paths]
test_targets = target_cache.Find(paths)
used_cache = True
if not test_targets:
used_cache = False
# Use gn refs to recursively find all targets that depend on |path|, filter
# internal gn targets, and match against well-known test suffixes, falling
# back to a list of known test targets if that fails.
gn_path = os.path.join(DEPOT_TOOLS_DIR, 'gn.py')
cmd = [sys.executable, gn_path, 'refs', out_dir, '--all'] + paths
targets = RunCommand(cmd).splitlines()
test_targets = _TestTargetsFromGnRefs(targets)
# If not targets were identified as tests by looking at their names, ask GN
# if any are executables.
if not test_targets and targets:
test_targets = RunCommand(cmd + ['--type=executable']).splitlines()
if not test_targets:
ExitWithMessage(
f'"{paths}" did not match any test targets. Consider adding'
f' one of the following targets to _TEST_TARGET_ALLOWLIST within '
f'{__file__}: \n' + '\n'.join(targets))
test_targets.sort()
target_cache.Store(paths, test_targets)
target_cache.Save()
if len(test_targets) > 1:
if run_all:
print(f'Warning, found {len(test_targets)} test targets.',
file=sys.stderr)
if len(test_targets) > 10:
ExitWithMessage('Your query likely involves non-test sources.')
print('Trying to run all of them!', file=sys.stderr)
else:
test_targets = [HaveUserPickTarget(paths, test_targets)]
# Remove the // prefix to turn GN label into ninja target.
test_targets = [t[2:] for t in test_targets]
return (test_targets, used_cache)
def RunTestTargets(out_dir, targets, gtest_filter, pref_mapping_filter,
extra_args, dry_run, no_try_android_wrappers,
no_fast_local_dev):
for target in targets:
target_binary = target.split(':')[1]
# Look for the Android wrapper script first.
path = os.path.join(out_dir, 'bin', f'run_{target_binary}')
if no_try_android_wrappers or not os.path.isfile(path):
# If the wrapper is not found or disabled use the Desktop target
# which is an executable.
path = os.path.join(out_dir, target_binary)
elif not no_fast_local_dev:
# Usually want this flag when developing locally.
extra_args = extra_args + ['--fast-local-dev']
cmd = [path, f'--gtest_filter={gtest_filter}']
if pref_mapping_filter:
cmd.append(f'--test_policy_to_pref_mappings_filter={pref_mapping_filter}')
cmd.extend(extra_args)
print('Running test: ' + shlex.join(cmd))
if not dry_run:
StreamCommandOrExit(cmd)
def BuildCppTestFilter(filenames, line):
make_filter_command = [
sys.executable, SRC_DIR / 'tools' / 'make_gtest_filter.py'
]
if line:
make_filter_command += ['--line', str(line)]
else:
make_filter_command += ['--class-only']
make_filter_command += filenames
return RunCommand(make_filter_command).strip()
def BuildJavaTestFilter(filenames):
return ':'.join('*.{}*'.format(os.path.splitext(os.path.basename(f))[0])
for f in filenames)
_PREF_MAPPING_GTEST_FILTER = '*PolicyPrefsTest.PolicyToPrefsMapping*'
_PREF_MAPPING_FILE_REGEX = re.compile(_PREF_MAPPING_FILE_PATTERN)
SPECIAL_TEST_FILTERS = [(_PREF_MAPPING_FILE_REGEX, _PREF_MAPPING_GTEST_FILTER)]
def BuildTestFilter(filenames, line):
java_files = [f for f in filenames if f.endswith('.java')]
# TODO(crbug.com/434009870): Support EarlGrey tests, which don't use
# Googletest's macros or pascal case naming convention.
cc_files = [
f for f in filenames if f.endswith('.cc') or f.endswith('_unittest.mm')
]
filters = []
if java_files:
filters.append(BuildJavaTestFilter(java_files))
if cc_files:
filters.append(BuildCppTestFilter(cc_files, line))
for regex, gtest_filter in SPECIAL_TEST_FILTERS:
if any(True for f in filenames if regex.match(f)):
filters.append(gtest_filter)
break
return ':'.join(filters)
def BuildPrefMappingTestFilter(filenames):
mapping_files = [f for f in filenames if _PREF_MAPPING_FILE_REGEX.match(f)]
if not mapping_files:
return None
names_without_extension = [Path(f).stem for f in mapping_files]
return ':'.join(names_without_extension)
def main():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--out-dir',
'--out_dir',
'--output-directory',
'--output_directory',
'-C',
metavar='OUT_DIR',
help='output directory of the build')
parser.add_argument('--remote-search',
'--remote_search',
'-r',
action='store_true',
help='Search for tests using a remote service')
parser.add_argument(
'--run-all',
'--run_all',
action='store_true',
help='Run all tests for the file or directory, instead of just one')
parser.add_argument('--line',
type=int,
help='run only the test on this line number. c++ only.')
parser.add_argument('--gtest-filter',
'--gtest_filter',
'-f',
metavar='FILTER',
help='test filter')
parser.add_argument('--test-policy-to-pref-mappings-filter',
'--test_policy_to_pref_mappings_filter',
metavar='FILTER',
help='policy pref mappings test filter')
parser.add_argument(
'--dry-run',
'--dry_run',
'-n',
action='store_true',
help='Print ninja and test run commands without executing them.')
parser.add_argument(
'--quiet',
'-q',
action='store_true',
help='Do not print while building, only print if build fails.')
parser.add_argument(
'--no-try-android-wrappers',
'--no_try_android_wrappers',
action='store_true',
help='Do not try to use Android test wrappers to run tests.')
parser.add_argument('--no-fast-local-dev',
'--no_fast_local_dev',
action='store_true',
help='Do not add --fast-local-dev for Android tests.')
parser.add_argument('files',
metavar='FILE_NAME',
nargs='+',
help='test suite file (eg. FooTest.java)')
args, _extras = parser.parse_known_args()
if args.out_dir:
constants.SetOutputDirectory(args.out_dir)
constants.CheckOutputDirectory()
out_dir: str = constants.GetOutDirectory()
if not os.path.isdir(out_dir):
parser.error(f'OUT_DIR "{out_dir}" does not exist.')
target_cache = TargetCache(out_dir)
filenames = []
for file in args.files:
filenames.extend(FindMatchingTestFiles(file, args.remote_search))
targets, used_cache = FindTestTargets(target_cache, out_dir, filenames,
args.run_all)
gtest_filter = args.gtest_filter
if not gtest_filter:
gtest_filter = BuildTestFilter(filenames, args.line)
if not gtest_filter:
ExitWithMessage('Failed to derive a gtest filter')
pref_mapping_filter = args.test_policy_to_pref_mappings_filter
if not pref_mapping_filter:
pref_mapping_filter = BuildPrefMappingTestFilter(filenames)
assert targets
build_ok = BuildTestTargets(out_dir, targets, args.dry_run, args.quiet)
# If we used the target cache, it's possible we chose the wrong target because
# a gn file was changed. The build step above will check for gn modifications
# and update build.ninja. Use this opportunity the verify the cache is still
# valid.
if used_cache and not target_cache.IsStillValid():
target_cache = TargetCache(out_dir)
new_targets, _ = FindTestTargets(target_cache, out_dir, filenames,
args.run_all)
if targets != new_targets:
# Note that this can happen, for example, if you rename a test target.
print('gn config was changed, trying to build again', file=sys.stderr)
targets = new_targets
build_ok = BuildTestTargets(out_dir, targets, args.dry_run, args.quiet)
if not build_ok: sys.exit(1)
RunTestTargets(out_dir, targets, gtest_filter, pref_mapping_filter, _extras,
args.dry_run, args.no_try_android_wrappers,
args.no_fast_local_dev)
if __name__ == '__main__':
sys.exit(main())
熬夜吃什么 女人吃当归有什么好处 小孩肠系膜淋巴结炎吃什么药 手臂有痣代表什么 为什么阴道会放气
女人什么身材最好看 为什么兔子的眼睛是红色的 备孕期间不能吃什么 学分是什么意思 安属于五行属什么
脑供血不足食补吃什么 味蕾是什么意思 小龙虾什么季节吃最好 中宫是什么意思 结婚的礼数都有什么
32岁属什么的生肖 巳时属什么生肖 东方为什么红 舌头不舒服是什么原因引起的 21三体综合征是指什么
一桌餐是什么意思hcv7jop9ns3r.cn 肾气亏虚吃什么中成药hcv9jop6ns4r.cn 外阴萎缩是什么症状hcv8jop8ns4r.cn 梦见自己和别人结婚是什么意思hcv8jop3ns1r.cn 21金维他什么时候吃效果最好hcv9jop4ns4r.cn
阿弥陀佛什么意思hcv8jop5ns0r.cn 痔疮不能吃什么食物clwhiglsz.com 胳肢窝疼痛是什么原因hcv8jop3ns0r.cn 近视散光是什么意思cl108k.com 神奇的近义词是什么hcv9jop6ns4r.cn
什么东西能让皮肤变白hcv8jop9ns0r.cn 更年期提前是什么症状hcv7jop9ns4r.cn 低血压吃什么好的最快女性hcv8jop5ns1r.cn 管教有方是什么意思hcv7jop5ns1r.cn 鸡精和鸡粉有什么区别hcv7jop6ns7r.cn
血肿是什么意思hcv8jop8ns8r.cn 情窦初开是什么意思jiuxinfghf.com 膝关节弹响是什么原因hcv7jop9ns8r.cn 给小孩办身份证需要什么hcv8jop3ns4r.cn 胃酸是什么颜色hcv9jop4ns6r.cn
百度