forked from mirrors/gecko-dev
Bug 1854553 - Introduce simple tests of Snap package r=releng-reviewers,taskgraph-reviewers,jmaher,jcristau
Differential Revision: https://phabricator.services.mozilla.com/D188932
This commit is contained in:
parent
7f347364e1
commit
09c8bc179c
8 changed files with 262 additions and 0 deletions
43
taskcluster/ci/snap-upstream-test/kind.yml
Normal file
43
taskcluster/ci/snap-upstream-test/kind.yml
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
---
|
||||||
|
loader: gecko_taskgraph.loader.transform:loader
|
||||||
|
|
||||||
|
only-for-attributes:
|
||||||
|
- build_platform
|
||||||
|
|
||||||
|
transforms:
|
||||||
|
- taskgraph.transforms.from_deps
|
||||||
|
- gecko_taskgraph.transforms.job
|
||||||
|
- gecko_taskgraph.transforms.task
|
||||||
|
- gecko_taskgraph.transforms.snap_test
|
||||||
|
|
||||||
|
kind-dependencies:
|
||||||
|
- snap-upstream-build
|
||||||
|
|
||||||
|
job-defaults:
|
||||||
|
treeherder:
|
||||||
|
kind: test
|
||||||
|
tier: 2
|
||||||
|
worker:
|
||||||
|
max-run-time: 900
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
basic:
|
||||||
|
from-deps:
|
||||||
|
group-by: single-with-filters
|
||||||
|
description: Runs basic tests on a Firefox Snap package
|
||||||
|
worker-type: t-linux-wayland
|
||||||
|
run:
|
||||||
|
using: run-task
|
||||||
|
checkout: false
|
||||||
|
command: >-
|
||||||
|
cd $MOZ_FETCHES_DIR/ && ./tests.sh
|
||||||
|
fetches:
|
||||||
|
snap-upstream-build:
|
||||||
|
- firefox.snap
|
||||||
|
- snap-tests.zip
|
||||||
|
treeherder:
|
||||||
|
platform: linux64/opt
|
||||||
|
symbol: Sel
|
||||||
|
|
@ -81,3 +81,10 @@ SNAPCRAFT_BUILD_ENVIRONMENT_CPU=$(nproc) \
|
||||||
CRAFT_PARTS_PACKAGE_REFRESH=0 \
|
CRAFT_PARTS_PACKAGE_REFRESH=0 \
|
||||||
snapcraft --destructive-mode --verbose
|
snapcraft --destructive-mode --verbose
|
||||||
cp ./*.snap ./*.debug /builds/worker/artifacts/
|
cp ./*.snap ./*.debug /builds/worker/artifacts/
|
||||||
|
|
||||||
|
# Those are for fetches usage by the test task
|
||||||
|
cp ./*.snap /builds/worker/artifacts/firefox.snap
|
||||||
|
cp ./*.debug /builds/worker/artifacts/firefox.debug
|
||||||
|
|
||||||
|
# Those are for running snap-upstream-test
|
||||||
|
cd /builds/worker/checkouts/gecko/taskcluster/docker/snap-coreXX-build/snap-tests/ && zip -r9 /builds/worker/artifacts/snap-tests.zip ./*
|
||||||
|
|
|
||||||
124
taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests.py
Normal file
124
taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests.py
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2022 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License version 3, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.common.exceptions import TimeoutException
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.firefox.options import Options
|
||||||
|
from selenium.webdriver.firefox.service import Service
|
||||||
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
class SnapTests:
|
||||||
|
def __init__(self, exp):
|
||||||
|
driver_service = Service(
|
||||||
|
executable_path=r"/snap/firefox/current/usr/lib/firefox/geckodriver"
|
||||||
|
)
|
||||||
|
options = Options()
|
||||||
|
options.binary_location = r"/snap/firefox/current/usr/lib/firefox/firefox"
|
||||||
|
options.add_argument("--headless")
|
||||||
|
self._driver = webdriver.Firefox(service=driver_service, options=options)
|
||||||
|
|
||||||
|
object_methods = [
|
||||||
|
method_name
|
||||||
|
for method_name in dir(self)
|
||||||
|
if callable(getattr(self, method_name))
|
||||||
|
]
|
||||||
|
|
||||||
|
self._wait = WebDriverWait(self._driver, self.get_timeout())
|
||||||
|
|
||||||
|
with open(exp, "r") as j:
|
||||||
|
self._expectations = json.load(j)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for m in object_methods:
|
||||||
|
if m.startswith("test_"):
|
||||||
|
print("Running: {}".format(m))
|
||||||
|
getattr(self, m)(self._expectations[m])
|
||||||
|
finally:
|
||||||
|
self._driver.quit()
|
||||||
|
|
||||||
|
def get_timeout(self):
|
||||||
|
if "TEST_TIMEOUT" in os.environ.keys():
|
||||||
|
return int(os.getenv("TEST_TIMEOUT"))
|
||||||
|
else:
|
||||||
|
return 5
|
||||||
|
|
||||||
|
def open_tab(self, url):
|
||||||
|
opened_tabs = len(self._driver.window_handles)
|
||||||
|
|
||||||
|
self._driver.switch_to.new_window("tab")
|
||||||
|
self._wait.until(EC.number_of_windows_to_be(opened_tabs + 1))
|
||||||
|
self._driver.get(url)
|
||||||
|
|
||||||
|
def test_about_support(self, exp):
|
||||||
|
self.open_tab("about:support")
|
||||||
|
|
||||||
|
version_box = self._wait.until(
|
||||||
|
EC.visibility_of_element_located((By.ID, "version-box"))
|
||||||
|
)
|
||||||
|
self._wait.until(lambda d: len(version_box.text) > 0)
|
||||||
|
print("about:support version: {}".format(version_box.text))
|
||||||
|
assert version_box.text == exp["version_box"]
|
||||||
|
|
||||||
|
distributionid_box = self._wait.until(
|
||||||
|
EC.visibility_of_element_located((By.ID, "distributionid-box"))
|
||||||
|
)
|
||||||
|
self._wait.until(lambda d: len(distributionid_box.text) > 0)
|
||||||
|
print("about:support distribution ID: {}".format(distributionid_box.text))
|
||||||
|
assert distributionid_box.text == exp["distribution_id"]
|
||||||
|
|
||||||
|
def test_youtube(self, exp):
|
||||||
|
self.open_tab("https://www.youtube.com")
|
||||||
|
|
||||||
|
# Wait for the consent dialog and accept it
|
||||||
|
print("Wait for consent form")
|
||||||
|
try:
|
||||||
|
self._wait.until(
|
||||||
|
EC.visibility_of_element_located(
|
||||||
|
(By.CSS_SELECTOR, "button[aria-label*=Accept]")
|
||||||
|
)
|
||||||
|
).click()
|
||||||
|
except TimeoutException:
|
||||||
|
print("Wait for consent form: timed out, maybe it is not here")
|
||||||
|
|
||||||
|
# Find first video and click it
|
||||||
|
print("Wait for one video")
|
||||||
|
self._wait.until(
|
||||||
|
EC.visibility_of_element_located((By.ID, "video-title-link"))
|
||||||
|
).click()
|
||||||
|
|
||||||
|
# Wait for duration to be set to something
|
||||||
|
print("Wait for video to start")
|
||||||
|
video = self._wait.until(
|
||||||
|
EC.visibility_of_element_located((By.CLASS_NAME, "html5-main-video"))
|
||||||
|
)
|
||||||
|
self._wait.until(lambda d: type(video.get_property("duration")) == float)
|
||||||
|
print("video duration: {}".format(video.get_property("duration")))
|
||||||
|
assert video.get_property("duration") > exp["duration"]
|
||||||
|
|
||||||
|
self._wait.until(lambda d: video.get_property("currentTime") > exp["playback"])
|
||||||
|
print("video played: {}".format(video.get_property("currentTime")))
|
||||||
|
assert video.get_property("currentTime") > exp["playback"]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
SnapTests(sys.argv[1])
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"test_about_support": {
|
||||||
|
"version_box": "#RUNTIME_VERSION#",
|
||||||
|
"distribution_id": "canonical-002"
|
||||||
|
},
|
||||||
|
"test_youtube": {
|
||||||
|
"duration": 1,
|
||||||
|
"playback": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
attrs==23.1.0
|
||||||
|
certifi==2023.7.22
|
||||||
|
exceptiongroup==1.1.3
|
||||||
|
h11==0.14.0
|
||||||
|
idna==3.4
|
||||||
|
outcome==1.2.0
|
||||||
|
PySocks==1.7.1
|
||||||
|
PyYAML==6.0.1
|
||||||
|
selenium==4.12.0
|
||||||
|
sniffio==1.3.0
|
||||||
|
sortedcontainers==2.4.0
|
||||||
|
trio==0.22.2
|
||||||
|
trio-websocket==0.10.4
|
||||||
|
urllib3==2.0.5
|
||||||
|
wsproto==1.2.0
|
||||||
17
taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh
Executable file
17
taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
sudo snap refresh --hold=24h firefox
|
||||||
|
|
||||||
|
sudo snap install --name firefox --dangerous ./firefox.snap
|
||||||
|
|
||||||
|
RUNTIME_VERSION=$(snap run firefox --version | awk '{ print $3 }')
|
||||||
|
|
||||||
|
python3 -m pip install --user -r requirements.txt
|
||||||
|
|
||||||
|
sed -e "s/#RUNTIME_VERSION#/${RUNTIME_VERSION}/#" < expectations.json.in > expectations.json
|
||||||
|
|
||||||
|
python3 basic_tests.py expectations.json
|
||||||
|
|
@ -798,3 +798,7 @@ Injects attribution information into localized installers.
|
||||||
snap-upstream-build
|
snap-upstream-build
|
||||||
-------------------
|
-------------------
|
||||||
Perform a Firefox Snap build using upstream tooling
|
Perform a Firefox Snap build using upstream tooling
|
||||||
|
|
||||||
|
snap-upstream-test
|
||||||
|
-------------------
|
||||||
|
Test a Firefox Snap built using upstream tooling
|
||||||
|
|
|
||||||
42
taskcluster/gecko_taskgraph/transforms/snap_test.py
Normal file
42
taskcluster/gecko_taskgraph/transforms/snap_test.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from taskgraph.transforms.base import TransformSequence
|
||||||
|
from taskgraph.util.dependencies import get_primary_dependency
|
||||||
|
from taskgraph.util.treeherder import inherit_treeherder_from_dep
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
transforms = TransformSequence()
|
||||||
|
|
||||||
|
|
||||||
|
@transforms.add
|
||||||
|
def fill_template(config, tasks):
|
||||||
|
for task in tasks:
|
||||||
|
dep = get_primary_dependency(config, task)
|
||||||
|
assert dep
|
||||||
|
|
||||||
|
inherit_treeherder_from_dep(task, dep)
|
||||||
|
task_platform = task["task"]["extra"]["treeherder"]["machine"]["platform"]
|
||||||
|
|
||||||
|
# Disambiguate the treeherder symbol.
|
||||||
|
full_platform_collection = (
|
||||||
|
task_platform + "-snap-" + task.get("label").split("-")[-1]
|
||||||
|
)
|
||||||
|
(platform, collection) = full_platform_collection.split("/")
|
||||||
|
task["task"]["extra"]["treeherder"]["collection"] = {collection: True}
|
||||||
|
task["task"]["extra"]["treeherder"]["machine"]["platform"] = platform
|
||||||
|
task["task"]["extra"]["treeherder-platform"] = full_platform_collection
|
||||||
|
|
||||||
|
timeout = 10
|
||||||
|
if collection != "opt":
|
||||||
|
timeout = 60
|
||||||
|
task["task"]["payload"]["env"]["TEST_TIMEOUT"] = "{}".format(timeout)
|
||||||
|
|
||||||
|
yield task
|
||||||
Loading…
Reference in a new issue