Auto merge of #21213 - servo:android-wpt, r=nox+jgraham

Add some support for WPT tests in an Android emulator through WebDriver

This succeeds on my machine:

`./mach test-wpt --product servodriver --binary etc/run_in_headless_android_emulator.py --binary-arg servo-x86 --binary-arg target/i686-linux-android/release/servo.apk /_mozilla/mozilla/DOMParser.html`

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21213)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-07-20 18:53:23 -04:00 committed by GitHub
commit 37a73d3bc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 256 additions and 76 deletions

View file

@ -37,7 +37,9 @@ def check_args(**kwargs):
def browser_kwargs(test_type, run_info_data, **kwargs):
return {
"binary": kwargs["binary"],
"binary_args": kwargs["binary_args"],
"debug_info": kwargs["debug_info"],
"server_config": kwargs["config"],
"user_stylesheets": kwargs.get("user_stylesheets"),
}
@ -71,16 +73,19 @@ def write_hosts_file(config):
class ServoWebDriverBrowser(Browser):
used_ports = set()
init_timeout = 300 # Large timeout for cases where we're booting an Android emulator
def __init__(self, logger, binary, debug_info=None, webdriver_host="127.0.0.1",
user_stylesheets=None):
server_config=None, binary_args=None, user_stylesheets=None):
Browser.__init__(self, logger)
self.binary = binary
self.binary_args = binary_args or []
self.webdriver_host = webdriver_host
self.webdriver_port = None
self.proc = None
self.debug_info = debug_info
self.hosts_path = write_hosts_file()
self.hosts_path = write_hosts_file(server_config)
self.server_ports = server_config.ports if server_config else {}
self.command = None
self.user_stylesheets = user_stylesheets if user_stylesheets else []
@ -91,10 +96,16 @@ class ServoWebDriverBrowser(Browser):
env = os.environ.copy()
env["HOST_FILE"] = self.hosts_path
env["RUST_BACKTRACE"] = "1"
env["EMULATOR_REVERSE_FORWARD_PORTS"] = ",".join(
str(port)
for _protocol, ports in self.server_ports.items()
for port in ports
if port
)
debug_args, command = browser_command(
self.binary,
[
self.binary_args + [
"--hard-fail",
"--webdriver", str(self.webdriver_port),
"about:blank",
@ -151,9 +162,10 @@ class ServoWebDriverBrowser(Browser):
def cleanup(self):
self.stop()
shutil.rmtree(os.path.dirname(self.hosts_file))
os.remove(self.hosts_path)
def executor_browser(self):
assert self.webdriver_port is not None
return ExecutorBrowser, {"webdriver_host": self.webdriver_host,
"webdriver_port": self.webdriver_port}
"webdriver_port": self.webdriver_port,
"init_timeout": self.init_timeout}

View file

@ -6,13 +6,16 @@ import time
import traceback
from .base import (Protocol,
BaseProtocolPart,
RefTestExecutor,
RefTestImplementation,
TestharnessExecutor,
strip_server)
from ..testrunner import Stop
from ..webdriver_server import wait_for_service
webdriver = None
ServoCommandExtensions = None
here = os.path.join(os.path.split(__file__)[0])
@ -23,20 +26,76 @@ def do_delayed_imports():
global webdriver
import webdriver
global ServoCommandExtensions
class ServoCommandExtensions(object):
def __init__(self, session):
self.session = session
@webdriver.client.command
def get_prefs(self, *prefs):
body = {"prefs": list(prefs)}
return self.session.send_session_command("POST", "servo/prefs/get", body)
@webdriver.client.command
def set_prefs(self, prefs):
body = {"prefs": prefs}
return self.session.send_session_command("POST", "servo/prefs/set", body)
@webdriver.client.command
def reset_prefs(self, *prefs):
body = {"prefs": list(prefs)}
return self.session.send_session_command("POST", "servo/prefs/reset", body)
def change_prefs(self, old_prefs, new_prefs):
# Servo interprets reset with an empty list as reset everything
if old_prefs:
self.reset_prefs(*old_prefs.keys())
self.set_prefs({k: parse_pref_value(v) for k, v in new_prefs.items()})
# See parse_pref_from_command_line() in components/config/opts.rs
def parse_pref_value(value):
if value == "true":
return True
if value == "false":
return False
try:
return float(value)
except ValueError:
return value
class ServoBaseProtocolPart(BaseProtocolPart):
def execute_script(self, script, async=False):
pass
def set_timeout(self, timeout):
pass
def wait(self):
pass
def set_window(self, handle):
pass
class ServoWebDriverProtocol(Protocol):
implements = [ServoBaseProtocolPart]
def __init__(self, executor, browser, capabilities, **kwargs):
do_delayed_imports()
Protocol.__init__(self, executor, browser)
self.capabilities = capabilities
self.host = browser.webdriver_host
self.port = browser.webdriver_port
self.init_timeout = browser.init_timeout
self.session = None
def connect(self):
"""Connect to browser via WebDriver."""
self.session = webdriver.Session(self.host, self.port,
extension=webdriver.servo.ServoCommandExtensions)
wait_for_service((self.host, self.port), timeout=self.init_timeout)
self.session = webdriver.Session(self.host, self.port, extension=ServoCommandExtensions)
self.session.start()
def after_connect(self):
@ -70,11 +129,6 @@ class ServoWebDriverProtocol(Protocol):
self.logger.error(traceback.format_exc(e))
break
def on_environment_change(self, old_environment, new_environment):
#Unset all the old prefs
self.session.extension.reset_prefs(*old_environment.get("prefs", {}).keys())
self.session.extension.set_prefs(new_environment.get("prefs", {}))
class ServoWebDriverRun(object):
def __init__(self, func, session, url, timeout, current_timeout=None):
@ -174,6 +228,12 @@ class ServoWebDriverTestharnessExecutor(TestharnessExecutor):
session.back()
return result
def on_environment_change(self, new_environment):
self.protocol.session.extension.change_prefs(
self.last_environment.get("prefs", {}),
new_environment.get("prefs", {})
)
class TimeoutError(Exception):
pass
@ -240,3 +300,9 @@ class ServoWebDriverRefTestExecutor(RefTestExecutor):
session.url = url
session.execute_async_script(self.wait_script)
return session.screenshot()
def on_environment_change(self, new_environment):
self.protocol.session.extension.change_prefs(
self.last_environment.get("prefs", {}),
new_environment.get("prefs", {})
)