Skip to content

Commit

Permalink
Merge pull request web-platform-tests#8987 from w3c/chrome-android
Browse files Browse the repository at this point in the history
wpt run for chome on android
  • Loading branch information
Jonathon Kereliuk authored Jan 12, 2018
2 parents aead36f + 996017f commit eb2d647
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 0 deletions.
35 changes: 35 additions & 0 deletions docs/_running-tests/chrome_android.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
To run WPT on Chrome on an android device, some additional set up is required.
First until we find a better way, we need to root the android device and update
the /etc/hosts file to include

```
127.0.0.1 web-platform.test
127.0.0.1 www.web-platform.test
127.0.0.1 www1.web-platform.test
127.0.0.1 www2.web-platform.test
127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test
127.0.0.1 xn--lve-6lad.web-platform.test
0.0.0.0 nonexistent-origin.web-platform.test
```

Next, we need to start adb and reverse forward the web-platform.tests ports

```
adb start-server
```

Add any ports that you need based on your config. For example:
```
adb reverse tcp:8000 tcp:8000
adb reverse tcp:8001 tcp:8001
adb reverse tcp:8081 tcp:8081
adb reverse tcp:8444 tcp:8444
adb reverse tcp:9001 tcp:9001
adb reverse tcp:9444 tcp:9444
```

After this, we may run wpt with the `chrome_android` product

```
./wpt run chrome_android <test>
```
55 changes: 55 additions & 0 deletions tools/wpt/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,61 @@ def prepare_environment(self):
logger.critical("dbus not running and can't be started")
sys.exit(1)

class ChromeAndroid(Browser):
"""Chrome-specific interface for android.
Includes installation, webdriver installation, and wptrunner setup methods.
"""

product = "chrome_android"
requirements = "requirements_chrome_android.txt"

def install(self, dest=None):
raise NotImplementedError

def platform_string(self):
raise NotImplementedError

def find_webdriver(self):
return find_executable("chromedriver")

def install_webdriver(self, dest=None):
"""Install latest Webdriver."""
if dest is None:
dest = os.pwd
latest = get("http://chromedriver.storage.googleapis.com/LATEST_RELEASE").text.strip()
url = "http://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip" % (latest,
self.platform_string())
unzip(get(url).raw, dest)

path = find_executable("chromedriver", dest)
st = os.stat(path)
os.chmod(path, st.st_mode | stat.S_IEXEC)
return path

def version(self, root):
raise NotImplementedError

def prepare_environment(self):
# https://bugs.chromium.org/p/chromium/issues/detail?id=713947
logger.debug("DBUS_SESSION_BUS_ADDRESS %s" % os.environ.get("DBUS_SESSION_BUS_ADDRESS"))
if "DBUS_SESSION_BUS_ADDRESS" not in os.environ:
if find_executable("dbus-launch"):
logger.debug("Attempting to start dbus")
dbus_conf = subprocess.check_output(["dbus-launch"])
logger.debug(dbus_conf)

# From dbus-launch(1):
#
# > When dbus-launch prints bus information to standard output,
# > by default it is in a simple key-value pairs format.
for line in dbus_conf.strip().split("\n"):
key, _, value = line.partition("=")
os.environ[key] = value
else:
logger.critical("dbus not running and can't be started")
sys.exit(1)


class Opera(Browser):
"""Opera-specific interface.
Expand Down
23 changes: 23 additions & 0 deletions tools/wpt/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,28 @@ def setup_kwargs(self, kwargs):
else:
raise WptrunError("Unable to locate or install chromedriver binary")

class ChromeAndroid(BrowserSetup):
name = "chrome_android"
browser_cls = browser.ChromeAndroid

def setup_kwargs(self, kwargs):
if kwargs["webdriver_binary"] is None:
webdriver_binary = self.browser.find_webdriver()

if webdriver_binary is None:
install = self.prompt_install("chromedriver")

if install:
print("Downloading chromedriver")
webdriver_binary = self.browser.install_webdriver(dest=self.venv.bin_path)
else:
print("Using webdriver binary %s" % webdriver_binary)

if webdriver_binary:
kwargs["webdriver_binary"] = webdriver_binary
else:
raise WptrunError("Unable to locate or install chromedriver binary")


class Opera(BrowserSetup):
name = "opera"
Expand Down Expand Up @@ -321,6 +343,7 @@ def setup_kwargs(self, kwargs):
product_setup = {
"firefox": Firefox,
"chrome": Chrome,
"chrome_android": ChromeAndroid,
"edge": Edge,
"ie": InternetExplorer,
"servo": Servo,
Expand Down
2 changes: 2 additions & 0 deletions tools/wptrunner/requirements_chrome_android.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mozprocess >= 0.19
selenium >= 2.41.0
1 change: 1 addition & 0 deletions tools/wptrunner/wptrunner/browsers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""

product_list = ["chrome",
"chrome_android",
"edge",
"firefox",
"ie",
Expand Down
98 changes: 98 additions & 0 deletions tools/wptrunner/wptrunner/browsers/chrome_android.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from .base import Browser, ExecutorBrowser, require_arg
from ..webdriver_server import ChromeDriverServer
from ..executors import executor_kwargs as base_executor_kwargs
from ..executors.executorselenium import (SeleniumTestharnessExecutor,
SeleniumRefTestExecutor)
from ..executors.executorchrome import ChromeDriverWdspecExecutor


__wptrunner__ = {"product": "chrome_android",
"check_args": "check_args",
"browser": "ChromeAndroidBrowser",
"executor": {"testharness": "SeleniumTestharnessExecutor",
"reftest": "SeleniumRefTestExecutor",
"wdspec": "ChromeDriverWdspecExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
"env_extras": "env_extras",
"env_options": "env_options"}


def check_args(**kwargs):
require_arg(kwargs, "webdriver_binary")


def browser_kwargs(test_type, run_info_data, **kwargs):
return {"binary": kwargs["binary"],
"webdriver_binary": kwargs["webdriver_binary"],
"webdriver_args": kwargs.get("webdriver_args")}


def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
**kwargs):
from selenium.webdriver import DesiredCapabilities

executor_kwargs = base_executor_kwargs(test_type, server_config,
cache_manager, **kwargs)
executor_kwargs["close_after_done"] = True
capabilities = dict(DesiredCapabilities.CHROME.items())
capabilities["chromeOptions"] = {}
# required to start on mobile
capabilities["chromeOptions"]["androidPackage"] = "com.android.chrome"

for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
if kwargs[kwarg] is not None:
capabilities["chromeOptions"][capability] = kwargs[kwarg]
if test_type == "testharness":
capabilities["useAutomationExtension"] = False
capabilities["excludeSwitches"] = ["enable-automation"]
if test_type == "wdspec":
capabilities["chromeOptions"]["w3c"] = True
executor_kwargs["capabilities"] = capabilities
return executor_kwargs


def env_extras(**kwargs):
return []


def env_options():
return {"host": "web-platform.test",
"bind_hostname": "true"}


class ChromeAndroidBrowser(Browser):
"""Chrome is backed by chromedriver, which is supplied through
``wptrunner.webdriver.ChromeDriverServer``.
"""

def __init__(self, logger, binary, webdriver_binary="chromedriver",
webdriver_args=None):
"""Creates a new representation of Chrome. The `binary` argument gives
the browser binary to use for testing."""
Browser.__init__(self, logger)
self.binary = binary
self.server = ChromeDriverServer(self.logger,
binary=webdriver_binary,
args=webdriver_args)

def start(self, **kwargs):
self.server.start(block=False)

def stop(self, force=False):
self.server.stop(force=force)

def pid(self):
return self.server.pid

def is_alive(self):
# TODO(ato): This only indicates the driver is alive,
# and doesn't say anything about whether a browser session
# is active.
return self.server.is_alive()

def cleanup(self):
self.stop()

def executor_browser(self):
return ExecutorBrowser, {"webdriver_url": self.server.url}

0 comments on commit eb2d647

Please sign in to comment.