Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

52
deps/v8/test/test262/tools/export.py vendored Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Pushes changes to test262 inside V8 to the upstream repo."""
from argparse import ArgumentParser
from pathlib import Path
import sys
def main():
parser = ArgumentParser()
parser.add_argument(
'-t',
'--blink-tools-path',
help=("Absolute path to where blink tools are located "
"(usually inside a local chromium checkout)."))
parser.add_argument(
'--config-path',
help="Absolute path to a project configuration json file.",
default=(Path(__file__).parent / 'v8configs.json'))
parser.add_argument(
'--approver',
help="Flag indicating that this run will only approve and merge "
"exisiting PRs. Approval of these PRs needs to be done by an account "
"different from the one that created the PR.",
action="store_true")
args, exporter_args = parser.parse_known_args(sys.argv)
sys.path.append(args.blink_tools_path)
from blinkpy.common import exit_codes
from blinkpy.common.host import Host
from blinkpy.common.path_finder import add_depot_tools_dir_to_os_path
from v8_exporter import V8TestExporter, V8TestApprover
from v8configs import config_from_file
add_depot_tools_dir_to_os_path()
host = Host(project_config_factory=config_from_file(args.config_path))
exporter = (V8TestApprover if args.approver else V8TestExporter)(host)
try:
success = exporter.main(exporter_args[1:])
host.exit(0 if success else 1)
except KeyboardInterrupt:
host.print_('Interrupted, exiting')
host.exit(exit_codes.INTERRUPTED_EXIT_STATUS)
if __name__ == '__main__':
main()

73
deps/v8/test/test262/tools/import.py vendored Normal file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env python3
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Pushes changes to test262 inside V8 to the upstream repo."""
from argparse import ArgumentParser
from pathlib import Path
import sys
def main():
parser = ArgumentParser()
parser.add_argument(
'-t',
'--blink-tools-path',
help=("Absolute path to where blink tools are located "
"(usually inside a local chromium checkout)."))
parser.add_argument(
'--config-path',
help="Absolute path to a project configuration json file.",
default=(Path(__file__).parent / 'v8configs.json'))
parser.add_argument(
'--phase',
help=("Phase of the import process to run. One of 'ALL', 'PREBUILD', "
"'POSTBUILD', 'UPLOAD'. ALL will run all phases; suitable for "
"local runs. PREBUILD and POSTBUILD are to be used when building "
"and running the tests is delegated to a proper builder. UPLOAD is "
"used for creating and uploading the CL for the import. UPLOAD is "
"deferred to the recipe on the import builder. This importer "
"script gets called twice on the builder, first with PREBUILD and "
"second with POSTBUILD. Build and UPLOAD phases are deferred to "
"the recipe on the builder."),
choices=['ALL', 'PREBUILD', 'POSTBUILD', 'UPLOAD'],
default='ALL')
parser.add_argument(
'--test262-failure-file',
help=('Absolute path to a file with names of the test to be skipped for '
'this import. Used only in PREBUILD phase.'),
default=None)
parser.add_argument(
'--v8-test262-last-revision',
help=('Used only in POSTBUILD when called separately. The old revision was'
' overwritten at this point by the PREBUILD phase.'),
default=None)
args, exporter_args = parser.parse_known_args(sys.argv)
sys.path.append(args.blink_tools_path)
from blinkpy.common import exit_codes
from blinkpy.common.host import Host
from blinkpy.common.path_finder import add_depot_tools_dir_to_os_path
from v8configs import config_from_file
from v8_importer import V8TestImporter
add_depot_tools_dir_to_os_path()
host = Host(project_config_factory=config_from_file(args.config_path))
importer = V8TestImporter(
phase=args.phase,
host=host,
test262_failure_file=args.test262_failure_file,
v8_test262_last_rev=args.v8_test262_last_revision)
try:
success = importer.main(exporter_args[1:])
host.exit(0 if success else 1)
except KeyboardInterrupt:
host.print_('Interrupted, exiting')
host.exit(exit_codes.INTERRUPTED_EXIT_STATUS)
if __name__ == '__main__':
main()

59
deps/v8/test/test262/tools/mocks.py vendored Normal file
View File

@ -0,0 +1,59 @@
# Copyright 2024 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Contains empty mocks for all blinkpy dependencies. When importing this module
all the necessary blinkpy imports are resolved to these mocks."""
import sys
sys.modules['blinkpy.w3c.local_wpt'] = __import__('mocks')
class LocalRepo:
pass
sys.modules['blinkpy.w3c.wpt_github'] = __import__('mocks')
class GitHubRepo:
pass
PROVISIONAL_PR_LABEL = 'provisional'
sys.modules['blinkpy.w3c.chromium_finder'] = __import__('mocks')
def absolute_chromium_dir():
pass
sys.modules['blinkpy.w3c.chromium_configs'] = __import__('mocks')
class ProjectConfig:
pass
sys.modules['blinkpy.common.system.log_utils'] = __import__('mocks')
def configure_logging():
pass
sys.modules['blinkpy.w3c.common'] = __import__('mocks')
def read_credentials():
pass
sys.modules['blinkpy.w3c.test_importer'] = __import__('mocks')
class TestImporter:
def __init__(self, *args, **kwargs):
pass

View File

@ -0,0 +1,86 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from requests.exceptions import HTTPError
from blinkpy.w3c.test_exporter import TestExporter
from blinkpy.w3c.wpt_github import GitHubError
import logging
_log = logging.getLogger(__name__)
PR_APPROVAL_LOGIN = 'test262-merge-bot'
class BaseV8TestExporter(TestExporter):
def export_in_flight_changes(self, pr_events) -> bool:
"""Test262 exporter ignores in-flight changes."""
pass
class V8TestExporter(BaseV8TestExporter):
def merge_pull_request(self, pull_request):
"""Exporter mode does not merge any PRs. We only create them."""
pass
class V8TestApprover(BaseV8TestExporter):
def merge_pull_request(self, pull_request):
"""Merges a pull request only if in approver mode."""
self.approve(pull_request.number)
super().merge_pull_request(pull_request)
def approve(self, pr_number):
"""Approves a PR.
Chromium/WPT exports are self approved via a web hook with self
approve functionality from an external github project
(https://github.com/web-platform-tests/wpt-pr-bot).
We will mimic the same behavior by sending an approve request just
before we attempt a second pass merge.
"""
if not self.is_approvable(pr_number):
return
body = {
'body': ('The review process for this patch is being conducted in '
'the V8 project.'),
'event': 'APPROVE',
'comments': [],
}
try:
response = self.github.request(
self.pr_path(pr_number), method='POST', body=body)
except HTTPError as e:
response = e.response
_log.error('Failed to approve PR %d: %s', pr_number, response.text)
def pr_path(self, pr_number):
return (f'/repos/{self.github.gh_org}/{self.github.gh_repo_name}'
f'/pulls/{pr_number}/reviews')
def is_approvable(self, pr_number):
"""Validates approval requirements."""
try:
response = self.github.request(self.pr_path(pr_number), method='GET')
reviews = response.data
reviewed_by_bot = any(
review['user']['login'] == PR_APPROVAL_LOGIN for review in reviews)
if reviewed_by_bot:
_log.info('PR %d already approved by us', pr_number)
return False
except HTTPError as e:
response = e.response
_log.error('Failed to get PR %d: %s', pr_number, response.text)
return False
return True
def create_or_update_pr_from_landed_commit(self, commit):
"""Approver mode does not create any PRs"""
pass

View File

@ -0,0 +1,391 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from abc import ABC, abstractmethod
from enum import Enum
from pathlib import Path
import argparse
import logging
import re
import shutil
import sys
from blinkpy.common.system.log_utils import configure_logging
from blinkpy.w3c.common import read_credentials
TEST_FILE_REFERENCE_IN_STATUS_FILE = re.compile("^\s*'(.*)':.*,$")
TEST262_FAILURE_LINE = re.compile("=== test262/(.*) ===")
TEST262_PATTERN = re.compile('^test/(.*)\.[^\s]*$')
TEST262_RENAME_PATTERN = re.compile('^R[^\s]*\s*([^\s]*)\s*([^\s]*)$')
TEST262_REPO_URL = 'https://chromium.googlesource.com/external/github.com/tc39/test262'
V8_TEST262_ROLLS_META_BUG = 'v8:7834'
_log = logging.getLogger(__file__)
class GitFileStatus(Enum):
ADDED = 'A'
DELETED = 'D'
MODIFIED = 'M'
UNKNOWN = 'X'
class V8TestImporter():
def __init__(self,
phase,
host,
test262_github=None,
test262_failure_file=None,
v8_test262_last_rev=None):
self.host = host
self.github = test262_github
self.project_config = host.project_config
self.project_root = Path(self.project_config.project_root)
self.test262_status_file = self.project_root / 'test' / 'test262' / 'test262.status'
self.phase = phase
self.test262_failure_file = test262_failure_file
self.v8_test262_last_rev = v8_test262_last_rev
def parse_args(self, argv):
parser = argparse.ArgumentParser()
parser.description = __doc__
parser.add_argument(
'-v',
'--verbose',
action='store_true',
help='log extra details that may be helpful when debugging')
parser.add_argument(
'--credentials-json',
help='A JSON file with GitHub credentials, '
'generally not necessary on developer machines')
return parser.parse_args(argv)
def main(self, argv=None):
options = self.parse_args(argv)
self.verbose = options.verbose
log_level = logging.DEBUG if self.verbose else logging.INFO
configure_logging(logging_level=log_level, include_time=True)
credentials = read_credentials(self.host, options.credentials_json)
gh_user = credentials.get('GH_USER')
gh_token = credentials.get('GH_TOKEN')
if not gh_user or not gh_token:
_log.warning('You have not set your GitHub credentials. This '
'script may fail with a network error when making '
'an API request to GitHub.')
_log.warning('See https://chromium.googlesource.com/chromium/src'
'/+/main/docs/testing/web_platform_tests.md'
'#GitHub-credentials for instructions on how to set '
'your credentials up.')
self.github = self.project_config.github_factory(self.host, gh_user,
gh_token)
test262_rev = self.fetch_test262(gh_token)
v8_test262_rev = (
self.v8_test262_last_rev or self.find_current_test262_rev())
if self.run_prebuild_phase():
if test262_rev == v8_test262_rev:
_log.info(f'No changes to import. {test262_rev} == {v8_test262_rev}')
return False
_log.info(f'Importing test262@{test262_rev} to V8')
self.roll_as_dependency(test262_rev)
self.overwrite_files()
self.sync_folders(v8_test262_rev, test262_rev)
failure_lines = []
if self.run_build_phase():
failure_lines = self.build_and_test()
# We either have the lines from the build phase or we read them from a file
# provided by the executor of POSTBUILD phase.
failure_lines = failure_lines or self.failure_lines_from_file()
if self.run_postbuild_phase():
self.update_status_file(v8_test262_rev, test262_rev, failure_lines)
# Output the import range for the recipe to pick up.
print(f'{TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}')
if self.run_upload_phase():
self.commit_and_upload_changes(v8_test262_rev, test262_rev)
# TODO: Create bug if status update yields a skip block
return True
@property
def test262_path(self):
return Path(self.local_test262.path)
def run_prebuild_phase(self):
return self.phase in ['ALL', 'PREBUILD']
def run_build_phase(self):
return self.phase in ['ALL']
def run_postbuild_phase(self):
return self.phase in ['ALL', 'POSTBUILD']
def run_upload_phase(self):
return self.phase in ['ALL', 'UPLOAD']
def fetch_test262(self, gh_token):
_log.info(f'Fetching test262')
self.local_test262 = self.project_config.local_repo_factory(
self.host, gh_token=gh_token)
self.local_test262.fetch()
self.test262_git = self.host.git(self.test262_path)
return self.test262_git.latest_git_commit()
def find_current_test262_rev(self):
_log.info(f'Finding current test262 revision in V8')
return self.host.executive.run_command(
['gclient', 'getdep', '-r', 'test/test262/data'],
cwd=self.project_root).splitlines()[-1].strip()
def roll_as_dependency(self, test262_rev):
self.host.executive.run_command(
['gclient', 'setdep', '-r', f'test/test262/data@{test262_rev}'],
cwd=self.project_root)
def overwrite_files(self):
for file in self.project_config.files_to_copy:
_log.info(f'Overwriting {file.destination} with {file.source}')
shutil.copyfile(
Path(self.local_test262.path) / file.source,
self.project_root / file.destination)
def sync_folders(self, v8_test262_rev, test262_rev):
for folder in self.project_config.paths_to_sync:
_log.info(f'Sync {folder.destination} with {folder.source}')
destination = self.project_root / folder.destination
for f in destination.glob('./**/*'):
if f.is_file() and not self.is_git_sync_exception(f):
relative_path = f.relative_to(destination)
source_file = self.test262_path / folder.source / relative_path
status = self.get_git_file_status(v8_test262_rev, test262_rev,
source_file)
self.update_file(f, status, source_file)
def is_git_sync_exception(self, file):
return file.name == 'features.txt'
def get_git_file_status(self, v8_test262_rev, test262_rev, source_file):
status_line = self.test262_git.run([
'diff', '--name-status', v8_test262_rev, test262_rev, '--', source_file
]).splitlines()
assert len(status_line) < 2, f'Expected zero or one line, got {status_line}'
if len(status_line) == 0:
return GitFileStatus.UNKNOWN
return GitFileStatus(status_line[0][0])
def update_file(self, local_file, status, source_file):
gfs = GitFileStatus
if status in [gfs.ADDED, gfs.DELETED, gfs.MODIFIED]:
_log.info(f'{local_file} has counterpart in Test262. Deleting.')
local_file.unlink()
else:
_log.warning(
f'{local_file} has no counterpart in Test262. '
'Maybe it was never exported?'
)
def build_and_test(self):
"""Builds and run test262 tests V8."""
_log.info('Building V8')
build_config = 'x64.release'
self.host.executive.run_command(
[sys.executable, 'tools/dev/gm.py', build_config],
cwd=self.project_root)
_log.info('Running test262 tests')
test_results = self.host.executive.run_command(
[
sys.executable, 'tools/run-tests.py',
f'--outdir=out/{build_config}', '--progress=verbose',
'--exit-after-n-failures=0', 'test262'
],
error_handler=testing_error_handler,
cwd=self.project_root).splitlines()
failure_matches = [TEST262_FAILURE_LINE.match(l) for l in test_results]
return uniq(m.group(1) for m in failure_matches if m)
def failure_lines_from_file(self):
if not self.test262_failure_file:
_log.warning('No failure file provided. Skipping.')
return []
with open(self.test262_failure_file, 'r') as r_file:
return r_file.readlines()
def update_status_file(self, v8_test262_rev, test262_rev, failure_lines):
_log.info(f'Updating status file')
updated_status = self.remove_and_rename(v8_test262_rev, test262_rev)
added_lines = self.failed_tests_to_status_lines(failure_lines)
if added_lines:
updated_status = self.rewrite_status_file_content(updated_status,
added_lines,
v8_test262_rev,
test262_rev)
with open(self.test262_status_file, 'w') as w_file:
w_file.writelines(updated_status)
def remove_and_rename(self, v8_test262_rev, test262_rev):
remover = DeletedTestsRemover(self, v8_test262_rev, test262_rev)
renamer = RenamedTestsUpdater(self, v8_test262_rev, test262_rev)
def updated_line(line):
return remover.updated_line(renamer.updated_line(line))
updated_status = [updated_line(line) for line in self.status_file_lines()]
return [line for line in updated_status if line is not None]
def status_file_lines(self):
with open(self.test262_status_file, 'r') as r_file:
return r_file.readlines()
def failed_tests_to_status_lines(self, failed_tests):
# Transform the list of failed tests into a list of status file lines.
return [f" '{test}': [FAIL],\n" for test in failed_tests]
def rewrite_status_file_content(self, updated_status, added_lines,
v8_test262_rev, test262_rev):
# Reassemble the status file with the new tests added.
# TODO(liviurau): This is easy to unit test. Add unit tests.
status_lines_before_eof = updated_status[:-2]
eof_status_lines = updated_status[-2:]
assert eof_status_lines == [
'\n', ']\n'
], f'Unexpected status file eof. {eof_status_lines}'
import_header_lines = [
'\n####\n', f'# Import test262@{test262_rev[:8]}\n',
f'# {TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}\n'
]
new_failing_tests_lines = ['[ALWAYS, {\n'] + added_lines + [
'}],\n', f'# End import test262@{test262_rev[:8]}\n', '####\n'
]
return (status_lines_before_eof + import_header_lines +
new_failing_tests_lines + eof_status_lines)
def commit_and_upload_changes(self, v8_test262_rev, test262_rev):
_log.info('Committing changes.')
self.project_git.run([
'commit',
'-a',
'-m',
'[test262] Roll test262',
'-m',
f'{TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}',
'-m',
'no-export: true',
])
_log.info('Uploading changes.')
self.project_git.run([
'cl',
'upload',
'--bypass-hooks',
'-f',
'-b',
V8_TEST262_ROLLS_META_BUG,
'-d',
])
_log.info(f'Issue: {self.project_git.run(["cl", "issue"]).strip()}')
def uniq(lst):
"""Return a list with unique elements from the input list."""
return sorted(set(lst))
def testing_error_handler(error):
"""Error handler that does nothing; used to suppress errors."""
pass
def relative_test_name(name):
"""Remove the test262 prefix from the test name."""
return re.sub(TEST262_PATTERN, r'\1', name)
class StatusFileUpdater(ABC):
def __init__(self, importer, v8_test262_rev, test262_rev, diff_args):
self.importer = importer
self.diff_args = diff_args
self.to_update = self.collect_updateable_tests(v8_test262_rev, test262_rev)
def updated_line(self, line):
test_name_result = TEST_FILE_REFERENCE_IN_STATUS_FILE.match(line)
if test_name_result:
return self.update_test_line(line, test_name_result)
return line
def collect_updateable_tests(self, v8_test262_rev, test262_rev):
lines = self.importer.test262_git.run([
'diff', *self.diff_args, v8_test262_rev, test262_rev, '--', 'test'
]).splitlines()
return self.process_git_output(lines)
@abstractmethod
def process_git_output(self, lines):
pass
@abstractmethod
def update_test_line(self, line, test_name_result):
pass
class DeletedTestsRemover(StatusFileUpdater):
def __init__(self, importer, v8_test262_rev, test262_rev):
super().__init__(importer, v8_test262_rev, test262_rev,
['--name-only', '--diff-filter=D'])
def process_git_output(self, lines):
return [
relative_test_name(line)
for line in lines
if TEST262_PATTERN.match(line)
]
def update_test_line(self, line, test_name_result):
test_name = test_name_result.group(1)
if test_name not in self.to_update:
return line
_log.info(f'... removing {test_name}')
return None
class RenamedTestsUpdater(StatusFileUpdater):
def __init__(self, importer, v8_test262_rev, test262_rev):
super().__init__(importer, v8_test262_rev, test262_rev,
['--name-status', '--diff-filter=R'])
def process_git_output(self, lines):
search_renames = [re.search(TEST262_RENAME_PATTERN, line) for line in lines]
renames = {
rename.group(1): rename.group(2) for rename in search_renames if rename
}
return {
relative_test_name(key): relative_test_name(value)
for key, value in renames.items()
if TEST262_PATTERN.match(key) and TEST262_PATTERN.match(value)
}
def update_test_line(self, line, test_name_result):
old_name = test_name_result.group(1)
new_name = self.to_update.get(old_name)
if not new_name:
return line
_log.info(f'... updating {old_name} to {new_name}')
return line.replace(old_name, new_name)

View File

@ -0,0 +1,190 @@
# Copyright 2024 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import mocks
import textwrap
import unittest
from pyfakefs import fake_filesystem_unittest
from v8_importer import (DeletedTestsRemover, GitFileStatus,
RenamedTestsUpdater, V8TestImporter)
from v8configs import to_object
fake_host = to_object({
'project_config': {
'project_root':
'.',
'paths_to_sync': [{
"source": "test/staging",
"destination": "test/test262/local-tests/test/staging"
}]
},
})
V8_REVISION = 'abcdef123456'
TEST262_REVISION = '123456abcdef'
class Test_TestV8Importer(fake_filesystem_unittest.TestCase):
def test_phases(self):
importer = V8TestImporter('ALL', fake_host)
self.assertTrue(importer.run_prebuild_phase())
self.assertTrue(importer.run_build_phase())
self.assertTrue(importer.run_postbuild_phase())
self.assertTrue(importer.run_upload_phase())
importer = V8TestImporter('PREBUILD', fake_host)
self.assertTrue(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertFalse(importer.run_postbuild_phase())
self.assertFalse(importer.run_upload_phase())
importer = V8TestImporter('POSTBUILD', fake_host)
self.assertFalse(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertTrue(importer.run_postbuild_phase())
self.assertFalse(importer.run_upload_phase())
importer = V8TestImporter('UPLOAD', fake_host)
self.assertFalse(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertFalse(importer.run_postbuild_phase())
self.assertTrue(importer.run_upload_phase())
def test_sync_folders(self):
self.setUpPyfakefs(allow_root_user=True)
destination = 'test/test262/local-tests/test/staging'
self.fs.create_file(f'{destination}/test1.js')
self.fs.create_file(f'{destination}/features.txt')
self.fs.create_file(f'{destination}/f1/test1.js')
self.fs.create_file(f'{destination}/f1/test2.js')
def get_git_file_status(*args):
path = str(args[2])
self.assertFalse(path.endswith('features.txt'))
return GitFileStatus.ADDED if path.endswith(
'test1.js') else GitFileStatus.UNKNOWN
importer = V8TestImporter('X', fake_host)
importer.local_test262 = to_object({
'path': '.',
})
importer.get_git_file_status = get_git_file_status
importer.sync_folders(V8_REVISION, TEST262_REVISION)
self.assertFalse(self.fs.exists(f'{destination}/test1.js'))
self.assertTrue(self.fs.exists(f'{destination}/features.txt'))
self.assertFalse(self.fs.exists(f'{destination}/f1/test1.js'))
self.assertTrue(self.fs.exists(f'{destination}/f1/test2.js'))
def test_remove_and_rename_tests(self):
self.setUpPyfakefs(allow_root_user=True)
self.fs.create_file(
'test/test262/test262.status',
contents=textwrap.dedent("""\
n'importe quoi
...
'folder1/sometest1': [FAIL],
'deleted_testname': [FAIL],
'renamed_testname': [FAIL],
'folder2/sometest1': [FAIL],
'folder2/sometest2': [FAIL],
...
"""))
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run':
lambda *args: 'test/deleted_testname.js\n'
'R001 test/renamed_testname.js test/updated_testname.js\n',
})
tests = importer.remove_and_rename(V8_REVISION, TEST262_REVISION)
self.assertEquals(
textwrap.dedent("""\
n'importe quoi
...
'folder1/sometest1': [FAIL],
'updated_testname': [FAIL],
'folder2/sometest1': [FAIL],
'folder2/sometest2': [FAIL],
...
"""), ''.join(tests))
def test_failed_tests_to_status_lines(self):
importer = V8TestImporter('X', fake_host)
result = importer.failed_tests_to_status_lines(['test1', 'test2'])
self.assertSequenceEqual([" 'test1': [FAIL],\n", " 'test2': [FAIL],\n"],
result)
def test_rewrite_status_file_content(self):
# Below \n is used inside the text block to avoid a trailing whitespace
# check
updated_status = textwrap.dedent("""\
some_testname
some random line
some other testname\n
]
""")
updated_status = updated_status.splitlines(keepends=True)
added_lines = [' new test 1\n', ' new test 2\n']
importer = V8TestImporter('X', fake_host)
result = importer.rewrite_status_file_content(updated_status, added_lines,
V8_REVISION, TEST262_REVISION)
self.assertEquals(textwrap.dedent("""\
some_testname
some random line
some other testname\n
####
# Import test262@123456ab
# https://chromium.googlesource.com/external/github.com/tc39/test262/+log/abcdef12..123456ab
[ALWAYS, {
new test 1
new test 2
}],
# End import test262@123456ab
####\n
]
"""), ''.join(result))
def test_deletion_updater(self):
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run': lambda *args: textwrap.dedent("""\
test/should_not_match.js extra garbage
test/should_not_match2.js
test/some_testname.js
practically garbage
"""),
})
updater = DeletedTestsRemover(importer, 'a', 'b')
self.assertEquals(['some_testname'], updater.to_update)
def test_rename_updater(self):
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run':
lambda *args: textwrap.dedent("""\
M test/should_not_match.js test/should_not_match.js
test/should_not_match2.js
R001 test/rename_testname.js test/updated_testname.js
R002 test/folder1/rename_testname.js test/folder2/updated_testname.js
practically garbage
"""),
})
updater = RenamedTestsUpdater(importer, 'a', 'b')
expected = {
'rename_testname': 'updated_testname',
'folder1/rename_testname': 'folder2/updated_testname',
}
self.assertEquals(expected, updater.to_update)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,45 @@
{
"github": {
"name": "Test262",
"org": "tc39",
"repo": "test262",
"main_branch": "main",
"patch_path_renames": [
{
"source": "test/test262/local-tests/test/staging/features.txt",
"destination": "features.txt"
},
{
"source": "test/test262/local-tests/test/staging",
"destination": "test/staging"
}
]
},
"gerrit": {
"revision_footer": "Test262-Export-Revision: ",
"relative_tests_path": "test/test262/local-tests/test/staging",
"project": "v8/v8",
"branch": "main"
},
"exporter": {
"pr_label": "v8-export",
"committer_email": "V8 Test262 Sync",
"committer_name": "v8-test262-autoroller@chromium.org",
"pr_updated_comment": "Successfully updated Test262 GitHub pull request with new revision \"{subject}\": {pr_url}",
"inflight_cl_comment": "Exportable changes to test262 were detected in this CL and a pull request in the upstream repo has been made: {pr_url}.\n\nWhen this CL lands, the bot will automatically merge the PR on GitHub if the required GitHub checks pass."
},
"importer": {
"files_to_copy": [
{
"source": "features.txt",
"destination": "test/test262/local-tests/test/staging/features.txt"
}
],
"paths_to_sync": [
{
"source": "test/staging",
"destination": "test/test262/local-tests/test/staging"
}
]
}
}

122
deps/v8/test/test262/tools/v8configs.py vendored Normal file
View File

@ -0,0 +1,122 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Contains all project-specific configuration and entities for V8/Tets262 host."""
import json
from functools import cached_property
from blinkpy.w3c.local_wpt import LocalRepo
from blinkpy.w3c.wpt_github import GitHubRepo, PROVISIONAL_PR_LABEL
from blinkpy.w3c.chromium_configs import ProjectConfig
def to_object(item):
"""
Recursively convert a dictionary to an object.
"""
if isinstance(item, dict):
return type('_dict_obj', (), {k: to_object(v) for k, v in item.items()})
if isinstance(item, list):
return [to_object(element) for element in item]
return item
class Test262GitHub(GitHubRepo):
def __init__(self,
config,
host,
user=None,
token=None,
pr_history_window=1000):
super(Test262GitHub, self).__init__(
gh_org=config.github.org,
gh_repo_name=config.github.repo,
export_pr_label=config.exporter.pr_label,
provisional_pr_label=PROVISIONAL_PR_LABEL,
host=host,
user=user,
token=token,
pr_history_window=pr_history_window,
main_branch=config.github.main_branch,
min_expected_prs=0)
@property
def skipped_revisions(self):
return [
# Revisions below would choke on github checks. Next revision in v8 repo
# is an effective reland.
"f4e862d29f6aeaa66b5e8e755dc70fe7cb2bc243",
"44702d6ea9c1bce9c95316e3aca41c14e0e8533f",
"87437c41113c2b41aaf5bcbc7fee996df0ab1711",
"b8d49712ab12dd13bee5da34849f8ab7f5309715",
"46c933180967191758afd0427f9d0ba02a4d24a3",
"85bf69fd70e118b1ace64110ed82cb1ff0d58533",
"b97d50ae5e4bb6b5abfc811c0b618d888c3f1377",
"c4946b3e60c597fb9d9cccb2b100647a945e309d",
]
class V8Test262Config(ProjectConfig):
def __init__(self, filesystem, config_file):
super().__init__(filesystem)
with open(config_file, 'r') as f:
self.config = to_object(json.loads(f.read()))
self.relative_tests_path = self.config.gerrit.relative_tests_path
self.revision_footer = self.config.gerrit.revision_footer
self.gerrit_project = self.config.gerrit.project
self.gerrit_branch = self.config.gerrit.branch
self.github_factory = github_factory(self.config)
self.local_repo_factory = local_repo_factory(self.config)
self.files_to_copy = self.config.importer.files_to_copy
self.paths_to_sync = self.config.importer.paths_to_sync
@cached_property
def project_root(self):
from blinkpy.common.system.executive import Executive
return Executive().run_command(
['git', 'rev-parse', '--show-toplevel']).strip()
@property
def test_root(self):
return self.project_root + '/' + self.relative_tests_path
@property
def import_destination_path(self):
return self.test_root
@property
def pr_updated_comment_template(self):
return self.config.exporter.pr_updated_comment
def inflight_cl_comment_template(self):
return self.config.exporter.inflight_cl_comment
def config_from_file(config_file):
return lambda filesystem: V8Test262Config(filesystem, config_file)
def local_repo_factory(config):
return lambda host, gh_token: LocalRepo(
name=config.github.name,
gh_org=config.github.org,
gh_repo_name=config.github.repo,
gh_ssh_url_template='https://{}@github.com/%s/%s.git' %
(config.github.org, config.github.repo),
mirror_url=None,
default_committer_email=config.exporter.committer_email,
default_committer_name=config.exporter.committer_name,
patch_path_renames=[(r.source, r.destination)
for r in config.github.patch_path_renames],
host=host,
gh_token=gh_token,
main_branch=config.github.main_branch,
)
def github_factory(config):
return lambda host, user, token: Test262GitHub(config, host, user, token)