Bug 1653696 [wpt PR 24651] - [wpt] Refactor tools.wpt (part 1), a=testonly

Automatic update from web-platform-tests
[wpt] Clean up --channel flag

Unify the two definitions of the --channel flag into one.

Drive-by: use logger in wpt.install isntead of print or sys.stdout.write

--
Remove the special case for FirefoxAndroid

There is no need to delay FirefoxAndroid.install() now that channel is
available to install().

Fix the definition of the Browser base class and update some docs. Also
add a test to make sure all subclasses are not abstract.

--
Update tools/wpt/tests/test_browser.py

Co-authored-by: Robert Ma <robertma@chromium.org>
--

wpt-commits: 9ddfd3cfc4239d82a429aed9c8aff6afb6035d36, 11787031d1257d4aea42d6506e90573298ab6b70, f85bd5cce97f04d357a361395750b3ce9149656d
wpt-pr: 24651
This commit is contained in:
Robert Ma 2020-07-22 20:02:28 +00:00 коммит произвёл moz-wptsync-bot
Родитель 3c66428304
Коммит a7cd55a1da
4 изменённых файлов: 73 добавлений и 58 удалений

Просмотреть файл

@ -70,17 +70,31 @@ class Browser(object):
:param channel: Browser channel to download
:param rename: Optional name for the downloaded package; the original
extension is preserved.
:return: The path to the downloaded package/installer
"""
return NotImplemented
@abstractmethod
def install(self, dest=None):
"""Install the browser."""
def install(self, dest=None, channel=None):
"""Download and install the browser.
This method usually calls download().
:param dest: Directory in which to install the browser
:param channel: Browser channel to install
:return: The path to the installed browser
"""
return NotImplemented
@abstractmethod
def install_webdriver(self, dest=None, channel=None, browser_binary=None):
"""Install the WebDriver implementation for this browser."""
"""Download and install the WebDriver implementation for this browser.
:param dest: Directory in which to install the WebDriver
:param channel: Browser channel to install
:param browser_binary: The path to the browser binary
:return: The path to the installed WebDriver
"""
return NotImplemented
@abstractmethod
@ -387,14 +401,14 @@ class Firefox(Browser):
tags = call("git", "ls-remote", "--tags", "--refs",
"https://github.com/mozilla/geckodriver.git")
release_re = re.compile(r".*refs/tags/v(\d+)\.(\d+)\.(\d+)")
latest_release = (0,0,0)
latest_release = (0, 0, 0)
for item in tags.split("\n"):
m = release_re.match(item)
if m:
version = tuple(int(item) for item in m.groups())
if version > latest_release:
latest_release = version
assert latest_release != (0,0,0)
assert latest_release != (0, 0, 0)
return "v%s.%s.%s" % tuple(str(item) for item in latest_release)
def install_webdriver(self, dest=None, channel=None, browser_binary=None):
@ -470,11 +484,14 @@ class FirefoxAndroid(Browser):
product = "firefox_android"
requirements = "requirements_firefox.txt"
def __init__(self, logger):
super(FirefoxAndroid, self).__init__(logger)
self.apk_path = None
def download(self, dest=None, channel=None, rename=None):
if dest is None:
dest = os.pwd
resp = get_taskcluster_artifact(
"gecko.v2.mozilla-central.latest.mobile.android-x86_64-opt",
"public/build/geckoview-androidTest.apk")
@ -482,12 +499,12 @@ class FirefoxAndroid(Browser):
filename = "geckoview-androidTest.apk"
if rename:
filename = "%s%s" % (rename, get_ext(filename)[1])
apk_path = os.path.join(dest, filename)
self.apk_path = os.path.join(dest, filename)
with open(apk_path, "wb") as f:
with open(self.apk_path, "wb") as f:
f.write(resp.content)
return apk_path
return self.apk_path
def install(self, dest=None, channel=None):
return self.download(dest, channel)
@ -497,7 +514,7 @@ class FirefoxAndroid(Browser):
return fx_browser.install_prefs(binary, dest, channel)
def find_binary(self, venv_path=None, channel=None):
raise NotImplementedError
return self.apk_path
def find_webdriver(self, channel=None):
raise NotImplementedError
@ -730,9 +747,9 @@ class ChromeAndroid(ChromeAndroidBase):
return "com.android.chrome"
#TODO(aluo): This is largely copied from the AndroidWebView implementation.
# Tests are not running for weblayer yet (crbug/1019521), this
# initial implementation will help to reproduce and debug any issues.
# TODO(aluo): This is largely copied from the AndroidWebView implementation.
# Tests are not running for weblayer yet (crbug/1019521), this initial
# implementation will help to reproduce and debug any issues.
class AndroidWeblayer(ChromeAndroidBase):
"""Weblayer-specific interface for Android."""

Просмотреть файл

@ -1,5 +1,4 @@
import argparse
import sys
from . import browser
latest_channels = {
@ -22,25 +21,27 @@ channel_by_name = {
'canary': 'canary',
}
channel_args = argparse.ArgumentParser(add_help=False)
channel_args.add_argument('--channel', choices=channel_by_name.keys(),
default='nightly', action='store',
help='''
Name of browser release channel (default: nightly). "stable" and "release" are
synonyms for the latest browser stable release; "beta" is the beta release;
"dev" is only meaningful for Chrome (i.e. Chrome Dev); "nightly",
"experimental", and "preview" are all synonyms for the latest available
development or trunk release. (For WebDriver installs, we attempt to select an
appropriate, compatible version for the latest browser release on the selected
channel.) This flag overrides --browser-channel.''')
def get_parser():
parser = argparse.ArgumentParser(description="""Install a given browser or webdriver frontend.
For convenience the release channel of the browser accepts various spellings,
but we actually support at most three variants; whatever the latest development
release is (e.g. Firefox nightly or Chrome dev), the latest beta release, and
the most recent stable release.""")
parser = argparse.ArgumentParser(
parents=[channel_args],
description="Install a given browser or webdriver frontend.")
parser.add_argument('browser', choices=['firefox', 'chrome', 'servo'],
help='name of web browser product')
parser.add_argument('component', choices=['browser', 'webdriver'],
help='name of component')
parser.add_argument('--channel', choices=channel_by_name.keys(),
default="nightly", help='Name of browser release channel. '
'"stable" and "release" are synonyms for the latest browser stable release,'
'"nightly", "dev", "experimental", and "preview" are all synonyms for '
'the latest available development release. For WebDriver installs, '
'we attempt to select an appropriate, compatible, version for the '
'latest browser release on the selected channel.')
parser.add_argument('--download-only', action="store_true",
help="Download the selected component but don't install it")
parser.add_argument('--rename', action="store", default=None,
@ -59,13 +60,15 @@ def get_channel(browser, channel):
def run(venv, **kwargs):
import logging
logger = logging.getLogger("install")
browser = kwargs["browser"]
destination = kwargs["destination"]
channel = get_channel(browser, kwargs["channel"])
if channel != kwargs["channel"]:
print("Interpreting channel '%s' as '%s'" % (kwargs["channel"],
channel))
logger.info("Interpreting channel '%s' as '%s'", kwargs["channel"], channel)
if destination is None:
if venv:
@ -77,7 +80,7 @@ def run(venv, **kwargs):
raise argparse.ArgumentError(None,
"No --destination argument, and no default for the environment")
install(browser, kwargs["component"], destination, channel,
install(browser, kwargs["component"], destination, channel, logger=logger,
download_only=kwargs["download_only"], rename=kwargs["rename"])
@ -92,11 +95,11 @@ def install(name, component, destination, channel="nightly", logger=None, downlo
method = prefix + suffix
subclass = getattr(browser, name.title())
sys.stdout.write('Now installing %s %s...\n' % (name, component))
browser_cls = getattr(browser, name.title())
logger.info('Now installing %s %s...', name, component)
kwargs = {}
if download_only and rename:
kwargs["rename"] = rename
path = getattr(subclass(logger), method)(dest=destination, channel=channel, **kwargs)
path = getattr(browser_cls(logger), method)(dest=destination, channel=channel, **kwargs)
if path:
sys.stdout.write('Binary %s as %s\n' % ("downloaded" if download_only else "installed", path,))
logger.info('Binary %s as %s', "downloaded" if download_only else "installed", path)

Просмотреть файл

@ -42,7 +42,7 @@ class WptrunnerHelpAction(argparse.Action):
def create_parser():
from wptrunner import wptcommandline
parser = argparse.ArgumentParser(add_help=False)
parser = argparse.ArgumentParser(add_help=False, parents=[install.channel_args])
parser.add_argument("product", action="store",
help="Browser to run tests in")
parser.add_argument("--affected", action="store", default=None,
@ -52,15 +52,6 @@ def create_parser():
parser.add_argument("--install-browser", action="store_true",
help="Install the browser from the release channel specified by --channel "
"(or the nightly channel by default).")
parser.add_argument("--channel", action="store",
choices=install.channel_by_name.keys(),
default=None, help='Name of browser release channel. '
'"stable" and "release" are synonyms for the latest browser stable '
'release, "nightly", "dev", "experimental", and "preview" are all '
'synonyms for the latest available development release. (For WebDriver '
'installs, we attempt to select an appropriate, compatible version for '
'the latest browser release on the selected channel.) '
'This flag overrides --browser-channel.')
parser._add_container_actions(wptcommandline.create_parser())
return parser
@ -182,6 +173,7 @@ class BrowserSetup(object):
def setup(self, kwargs):
self.setup_kwargs(kwargs)
def safe_unsetenv(env_var):
"""Safely remove an environment variable.
@ -193,6 +185,7 @@ def safe_unsetenv(env_var):
except KeyError:
pass
class Firefox(BrowserSetup):
name = "firefox"
browser_cls = browser.Firefox
@ -264,11 +257,6 @@ class FirefoxAndroid(BrowserSetup):
name = "firefox_android"
browser_cls = browser.FirefoxAndroid
def install(self, channel):
# The install needs to happen in setup so that we have access to all the kwargs
self._install_browser = True
return None
def setup_kwargs(self, kwargs):
from . import android
import mozdevice
@ -295,13 +283,6 @@ class FirefoxAndroid(BrowserSetup):
emulator = android.install(logger, reinstall=False, no_prompt=not self.prompt)
android.start(logger, emulator=emulator, reinstall=False)
install = False
if hasattr(self, "_install_browser"):
if self.prompt_install("geckoview-test"):
install = True
apk_path = self.browser.install(self.venv.path,
channel=kwargs["browser_channel"])
if "ADB_PATH" not in os.environ:
adb_path = os.path.join(android.get_sdk_path(None),
"platform-tools",
@ -312,9 +293,9 @@ class FirefoxAndroid(BrowserSetup):
device = mozdevice.ADBDeviceFactory(adb=adb_path,
device=kwargs["device_serial"])
if install:
if self.browser.apk_path:
device.uninstall_app(app)
device.install_app(apk_path)
device.install_app(self.browser.apk_path)
elif not device.is_app_installed(app):
raise WptrunError("app %s not installed on device %s" %
(app, kwargs["device_serial"]))

Просмотреть файл

@ -3,6 +3,7 @@ import subprocess
import logging
import sys
import pytest
import inspect
from tools.wpt import browser
@ -10,6 +11,19 @@ from tools.wpt import browser
logger = logging.getLogger()
def test_all_browser_abc():
# Make sure all subclasses of Browser implement all abstract methods
# (except some known base classes). This is a basic sanity test in case
# we change the ABC interface of Browser as we only instantiate some
# products in unit tests.
classes = inspect.getmembers(browser)
for name, cls in classes:
if cls in (browser.Browser, browser.ChromeAndroidBase):
continue
if inspect.isclass(cls) and issubclass(cls, browser.Browser):
assert not inspect.isabstract(cls), "%s is abstract" % name
@mock.patch('subprocess.check_output')
def test_safari_version(mocked_check_output):
safari = browser.Safari(logger)